pax_global_header00006660000000000000000000000064147466445160014533gustar00rootroot0000000000000052 comment=db9cc73250255c0719dcd674671003f7aeade379 cue-lang-cue-db9cc73/000077500000000000000000000000001474664451600145005ustar00rootroot00000000000000cue-lang-cue-db9cc73/.gitattributes000066400000000000000000000001211474664451600173650ustar00rootroot00000000000000# To prevent CRLF breakages on Windows for fragile files, like testdata. * -text cue-lang-cue-db9cc73/.github/000077500000000000000000000000001474664451600160405ustar00rootroot00000000000000cue-lang-cue-db9cc73/.github/CODEOWNERS000066400000000000000000000000131474664451600174250ustar00rootroot00000000000000* @cueckoo cue-lang-cue-db9cc73/.github/ISSUE_TEMPLATE/000077500000000000000000000000001474664451600202235ustar00rootroot00000000000000cue-lang-cue-db9cc73/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000013121474664451600227120ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: NeedsInvestigation, Triage assignees: '' --- ### What version of CUE are you using (`cue version`)?
$ cue version

### Does this issue reproduce with the latest stable release? ### What did you do? ### What did you expect to see? ### What did you see instead? cue-lang-cue-db9cc73/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000000341474664451600222100ustar00rootroot00000000000000blank_issues_enabled: false cue-lang-cue-db9cc73/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000011471474664451600237530ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: FeatureRequest, Triage assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. cue-lang-cue-db9cc73/.github/ISSUE_TEMPLATE/z.md000066400000000000000000000001331474664451600210130ustar00rootroot00000000000000--- name: Blank issue about: For anything else title: '' labels: Triage assignees: '' --- cue-lang-cue-db9cc73/.github/workflows/000077500000000000000000000000001474664451600200755ustar00rootroot00000000000000cue-lang-cue-db9cc73/.github/workflows/evict_caches.yaml000066400000000000000000000137761474664451600234170ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. name: Evict caches "on": schedule: - cron: 0 2 * * * jobs: test: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} if: ${{github.repository == 'cue-lang/cue'}} runs-on: ubuntu-24.04 steps: - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: Reset git directory modification times run: touch -t 202211302355 $(find * -type d) - name: Restore git file modification times uses: chetan/git-restore-mtime-action@075f9bc9d159805603419d50f794bd9f33252ebe - name: Try to extract Dispatch-Trailer id: DispatchTrailer run: |- x="$(git log -1 --pretty='%(trailers:key=Dispatch-Trailer,valueonly)')" if [[ "$x" == "" ]] then # Some steps rely on the presence or otherwise of the Dispatch-Trailer. # We know that we don't have a Dispatch-Trailer in this situation, # hence we use the JSON value null in order to represent that state. # This means that GitHub expressions can determine whether a Dispatch-Trailer # is present or not by checking whether the fromJSON() result of the # output from this step is the JSON value null or not. x=null fi echo "value<> $GITHUB_OUTPUT echo "$x" >> $GITHUB_OUTPUT echo "EOD" >> $GITHUB_OUTPUT - name: Check we don't have Dispatch-Trailer on a protected branch if: |- ((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) && (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')) run: |- echo "github.event.head_commit.message contains Dispatch-Trailer but we are on a protected branch" false - name: Delete caches run: |- set -x echo ${{ secrets.CUECKOO_GITHUB_PAT }} | gh auth login --with-token gh extension install actions/gh-actions-cache for i in https://github.com/cue-lang/cue https://github.com/cue-lang/cue-trybot do echo "Evicting caches for $i" cd $(mktemp -d) git init -b initialbranch git remote add origin $i for j in $(gh actions-cache list -L 100 | grep refs/ | awk '{print $1}') do gh actions-cache delete --confirm $j done done - name: Trigger workflow runs to repopulate caches run: |- # Prepare git for pushes to trybot repo. Note # because we have already checked out code we don't # need origin. Fetch origin default branch for later use git config user.name cueckoo git config user.email cueckoo@gmail.com git config http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n cueckoo:${{ secrets.CUECKOO_GITHUB_PAT }} | base64)" git remote add trybot https://github.com/cue-lang/cue-trybot # Now trigger the most recent workflow run on each of the default branches. # We do this by listing all the branches on the main repo and finding those # which match the protected branch patterns (globs). for j in $(curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.CUECKOO_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" -f https://api.github.com/repos/cue-lang/cue/branches | jq -r '.[] | .name') do for i in master release-branch.* do if [[ "$j" != $i ]]; then continue fi echo Branch: $j sha=$(curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.CUECKOO_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" "https://api.github.com/repos/cue-lang/cue/commits/$j" | jq -r '.sha') echo Latest commit: $sha echo "Trigger workflow on cue-lang/cue" curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.CUECKOO_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" --fail-with-body -X POST https://api.github.com/repos/cue-lang/cue/actions/workflows/trybot.yaml/dispatches -d "{\"ref\":\"$j\"}" # Ensure that the trybot repo has the latest commit for # this branch. If the force-push results in a commit # being pushed, that will trigger the trybot workflows # so we don't need to do anything, otherwise we need to # trigger the most recent commit on that branch git remote -v git fetch origin refs/heads/$j git log -1 FETCH_HEAD success=false for try in {1..20}; do echo "Push to trybot try $try" exitCode=0; push="$(git push -f trybot FETCH_HEAD:$j 2>&1)" || exitCode=$? echo "$push" if [[ $exitCode -eq 0 ]]; then success=true break fi sleep 1 done if ! $success; then echo "Giving up" exit 1 fi if echo "$push" | grep up-to-date then # We are up-to-date, i.e. the push did nothing, hence we need to trigger a workflow_dispatch # in the trybot repo. echo "Trigger workflow on cue-lang/cue-trybot" curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.CUECKOO_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" --fail-with-body -X POST https://api.github.com/repos/cue-lang/cue-trybot/actions/workflows/trybot.yaml/dispatches -d "{\"ref\":\"$j\"}" else echo "Force-push to cue-lang/cue-trybot did work; nothing to do" fi done done cue-lang-cue-db9cc73/.github/workflows/push_tip_to_trybot.yaml000066400000000000000000000030071474664451600247210ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. concurrency: push_tip_to_trybot jobs: push: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} runs-on: ubuntu-24.04 if: ${{github.repository == 'cue-lang/cue'}} steps: - name: Write netrc file for cueckoo Gerrithub run: |- cat < ~/.netrc machine review.gerrithub.io login cueckoo password ${{ secrets.CUECKOO_GERRITHUB_PASSWORD }} EOD chmod 600 ~/.netrc - name: Push tip to trybot run: |- mkdir tmpgit cd tmpgit git init -b initialbranch git config user.name cueckoo git config user.email cueckoo@gmail.com git config http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n cueckoo:${{ secrets.CUECKOO_GITHUB_PAT }} | base64)" git remote add origin https://review.gerrithub.io/a/cue-lang/cue git remote add trybot https://github.com/cue-lang/cue-trybot git fetch origin "${{ github.ref }}" success=false for try in {1..20}; do echo "Push to trybot try $try" if git push -f trybot "FETCH_HEAD:${{ github.ref }}"; then success=true break fi sleep 1 done if ! $success; then echo "Giving up" exit 1 fi name: Push tip to trybot "on": push: branches: - master - release-branch.* cue-lang-cue-db9cc73/.github/workflows/release.yaml000066400000000000000000000102561474664451600224050ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. name: Release concurrency: release "on": push: tags: - v* - '!*-0.dev' branches: - ci/test - master - release-branch.* jobs: goreleaser: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} runs-on: ubuntu-24.04 if: ${{github.repository == 'cue-lang/cue'}} steps: - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: Reset git directory modification times run: touch -t 202211302355 $(find * -type d) - name: Restore git file modification times uses: chetan/git-restore-mtime-action@075f9bc9d159805603419d50f794bd9f33252ebe - id: DispatchTrailer name: Try to extract Dispatch-Trailer run: |- x="$(git log -1 --pretty='%(trailers:key=Dispatch-Trailer,valueonly)')" if [[ "$x" == "" ]] then # Some steps rely on the presence or otherwise of the Dispatch-Trailer. # We know that we don't have a Dispatch-Trailer in this situation, # hence we use the JSON value null in order to represent that state. # This means that GitHub expressions can determine whether a Dispatch-Trailer # is present or not by checking whether the fromJSON() result of the # output from this step is the JSON value null or not. x=null fi echo "value<> $GITHUB_OUTPUT echo "$x" >> $GITHUB_OUTPUT echo "EOD" >> $GITHUB_OUTPUT - if: |- ((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) && (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')) name: Check we don't have Dispatch-Trailer on a protected branch run: |- echo "github.event.head_commit.message contains Dispatch-Trailer but we are on a protected branch" false - name: Install Go uses: actions/setup-go@v5 with: cache: false go-version: 1.23.5 - name: Set common go env vars run: |- go env -w GOTOOLCHAIN=local # Dump env for good measure go env - name: Setup qemu uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Docker Login uses: docker/login-action@v3 with: registry: docker.io username: cueckoo password: ${{ secrets.CUECKOO_DOCKER_PAT }} - name: Install CUE run: go install ./cmd/cue - name: Install GoReleaser uses: goreleaser/goreleaser-action@v5 with: install-only: true version: v2.5.0 - name: Run GoReleaser with CUE env: CUE_TOKEN: ${{ secrets.NOTCUECKOO_CUE_TOKEN }} GITHUB_TOKEN: ${{ secrets.CUECKOO_GITHUB_PAT }} run: |- go run cuelang.org/go/cmd/cue login --token=${CUE_TOKEN} cue cmd release working-directory: ./internal/ci/goreleaser - if: startsWith(github.ref, 'refs/tags/v') name: Re-test cuelang.org run: 'curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.CUECKOO_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" --fail --request POST --data-binary "{\"event_type\":\"Re-test post release of ${GITHUB_REF##refs/tags/}\"}" https://api.github.com/repos/cue-lang/cuelang.org/dispatches' - if: startsWith(github.ref, 'refs/tags/v') name: Trigger unity build run: 'curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.PORCUEPINE_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" --fail --request POST --data-binary "{\"event_type\":\"Check against CUE ${GITHUB_REF##refs/tags/}\",\"client_payload\":{\"type\":\"unity\",\"payload\":{\"versions\":\"\\\"${GITHUB_REF##refs/tags/}\\\"\"}}}" https://api.github.com/repos/cue-unity/unity-private/dispatches' cue-lang-cue-db9cc73/.github/workflows/tip_triggers.yaml000066400000000000000000000021701474664451600234630ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. name: Triggers on push to tip "on": push: branches: - master - ci/test jobs: push: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} runs-on: ubuntu-24.04 if: ${{github.repository == 'cue-lang/cue'}} steps: - name: Trigger unity build run: 'curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.PORCUEPINE_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" --fail --request POST --data-binary "{\"event_type\":\"Check against ${GITHUB_SHA}\",\"client_payload\":{\"type\":\"unity\",\"payload\":{\"versions\":\"\\\"commit:${GITHUB_SHA}\\\"\"}}}" https://api.github.com/repos/cue-unity/unity-private/dispatches' - name: Trigger cuelang.org tipdeploy run: 'curl -s -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.CUECKOO_GITHUB_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" --fail --request POST --data-binary "{\"ref\":\"master\"}" https://api.github.com/repos/cue-lang/cuelang.org/actions/workflows/tipdeploy.yaml/dispatches' cue-lang-cue-db9cc73/.github/workflows/trybot.yaml000066400000000000000000000207511474664451600223110ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. name: TryBot "on": push: branches: - ci/test - master - release-branch.* tags-ignore: - v* pull_request_target: {} workflow_dispatch: {} jobs: test: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} strategy: fail-fast: false matrix: go-version: - 1.22.x - 1.23.x runner: - ubuntu-24.04 - macos-14 - windows-2022 runs-on: ${{ matrix.runner }} if: |- (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"trybot"')) || ! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')) steps: - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: Reset git directory modification times run: touch -t 202211302355 $(find * -type d) - name: Restore git file modification times uses: chetan/git-restore-mtime-action@075f9bc9d159805603419d50f794bd9f33252ebe - id: DispatchTrailer name: Try to extract Dispatch-Trailer run: |- x="$(git log -1 --pretty='%(trailers:key=Dispatch-Trailer,valueonly)')" if [[ "$x" == "" ]] then # Some steps rely on the presence or otherwise of the Dispatch-Trailer. # We know that we don't have a Dispatch-Trailer in this situation, # hence we use the JSON value null in order to represent that state. # This means that GitHub expressions can determine whether a Dispatch-Trailer # is present or not by checking whether the fromJSON() result of the # output from this step is the JSON value null or not. x=null fi echo "value<> $GITHUB_OUTPUT echo "$x" >> $GITHUB_OUTPUT echo "EOD" >> $GITHUB_OUTPUT - if: |- ((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) && (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')) name: Check we don't have Dispatch-Trailer on a protected branch run: |- echo "github.event.head_commit.message contains Dispatch-Trailer but we are on a protected branch" false - name: Install Go uses: actions/setup-go@v5 with: cache: false go-version: ${{ matrix.go-version }} - name: Set common go env vars run: |- go env -w GOTOOLCHAIN=local # Dump env for good measure go env - id: go-mod-cache-dir name: Get go mod cache directory run: echo "dir=$(go env GOMODCACHE)" >> ${GITHUB_OUTPUT} - id: go-cache-dir name: Get go build/test cache directory run: echo "dir=$(go env GOCACHE)" >> ${GITHUB_OUTPUT} - if: |- (((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || (github.ref == 'refs/heads/ci/test')) uses: actions/cache@v4 with: path: |- ${{ steps.go-mod-cache-dir.outputs.dir }}/cache/download ${{ steps.go-cache-dir.outputs.dir }} key: ${{ runner.os }}-${{ matrix.go-version }}-${{ github.run_id }} restore-keys: ${{ runner.os }}-${{ matrix.go-version }} - if: |- ! (((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || (github.ref == 'refs/heads/ci/test')) uses: actions/cache/restore@v4 with: path: |- ${{ steps.go-mod-cache-dir.outputs.dir }}/cache/download ${{ steps.go-cache-dir.outputs.dir }} key: ${{ runner.os }}-${{ matrix.go-version }}-${{ github.run_id }} restore-keys: ${{ runner.os }}-${{ matrix.go-version }} - if: |- github.repository == 'cue-lang/cue' && (((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || github.ref == 'refs/heads/ci/test') run: go clean -testcache - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Early git and code sanity checks run: go run ./internal/ci/checks - if: |- ((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || !(matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Test run: go test ./... - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Test with -race env: GORACE: atexit_sleep_ms=10 run: go test -race ./... - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Test on 32 bits env: GOARCH: "386" run: go test -short ./... - name: Test with -tags=cuewasm run: go test -tags cuewasm ./cmd/cue/cmd ./cue/interpreter/wasm - id: auth uses: google-github-actions/auth@v2 with: credentials_json: ${{ secrets.E2E_GCLOUD_KEY }} if: |- github.repository == 'cue-lang/cue' && (((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || (github.ref == 'refs/heads/ci/test')) && (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: gcloud auth for end-to-end tests - if: |- github.repository == 'cue-lang/cue' && (((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || (github.ref == 'refs/heads/ci/test')) && (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: gcloud setup for end-to-end tests uses: google-github-actions/setup-gcloud@v2 - if: |- github.repository == 'cue-lang/cue' && (((github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-branch.')) && (! (contains(github.event.head_commit.message, ' Dispatch-Trailer: {"type":"')))) || (github.ref == 'refs/heads/ci/test')) && (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: End-to-end test run: |- cd internal/_e2e go test -race env: CUE_TEST_TOKEN: ${{ secrets.E2E_PORCUEPINE_CUE_TOKEN }} - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Go checks run: |- go vet ./... go mod tidy (cd internal/_e2e && go test -run=-) - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: staticcheck uses: dominikh/staticcheck-action@v1 with: version: 2024.1.1 install-go: false - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Check all git tags are available run: |- cd $(mktemp -d) git ls-remote --tags https://github.com/cue-lang/cue >github.txt echo "GitHub tags:" sed 's/^/ /' github.txt git ls-remote --tags https://review.gerrithub.io/cue-lang/cue >gerrit.txt if ! diff -u github.txt gerrit.txt; then echo "GitHub and Gerrit do not agree on the list of tags!" echo "Did you forget about refs/attic branches? https://github.com/cue-lang/cue/wiki/Notes-for-project-maintainers" exit 1 fi - if: (matrix.go-version == '1.23.x' && matrix.runner == 'ubuntu-24.04') name: Generate env: CUE_TOKEN: ${{ secrets.NOTCUECKOO_CUE_TOKEN }} run: |- go run cuelang.org/go/cmd/cue login --token=${CUE_TOKEN} go generate ./... - if: always() name: Check that git is clean at the end of the job run: test -z "$(git status --porcelain)" || (git status; git diff; false) cue-lang-cue-db9cc73/.github/workflows/trybot_dispatch.yaml000066400000000000000000000126151474664451600241700ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. name: Dispatch trybot "on": repository_dispatch: {} push: branches: - ci/test jobs: trybot: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} runs-on: ubuntu-24.04 if: ${{ ((github.ref == 'refs/heads/ci/test') && false) || github.event.client_payload.type == 'trybot' }} steps: - name: Write netrc file for cueckoo Gerrithub run: |- cat < ~/.netrc machine review.gerrithub.io login cueckoo password ${{ secrets.CUECKOO_GERRITHUB_PASSWORD }} EOD chmod 600 ~/.netrc - id: payload if: github.repository == 'cue-lang/cue' && (github.ref == 'refs/heads/ci/test') name: Write fake payload run: |- cat <> $GITHUB_OUTPUT value<security@cuelang.org. ## Becoming a code contributor The code contribution process used by the CUE project is a little different from that used by other open source projects. We assume you have a basic understanding of [`git`](https://git-scm.com/) and [Go](https://golang.org) (1.22 or later). The first thing to decide is whether you want to contribute a code change via GitHub or GerritHub. Both workflows are fully supported, and whilst GerritHub is used by the core project maintainers as the "source of truth", the GitHub Pull Request workflow is 100% supported - contributors should feel entirely comfortable contributing this way if they prefer. Contributions via either workflow must be accompanied by a Developer Certificate of Origin. ### Asserting a Developer Certificate of Origin Contributions to the CUE project must be accompanied by a [Developer Certificate of Origin](https://developercertificate.org/), we are using version 1.1. All commit messages must contain the `Signed-off-by` line with an email address that matches the commit author. This line asserts the Developer Certificate of Origin. When committing, use the `--signoff` (or `-s`) flag: ```console $ git commit -s ``` You can also [set up a prepare-commit-msg git hook](#do-i-really-have-to-add-the--s-flag-to-each-commit) to not have to supply the `-s` flag. The explanations of the GitHub and GerritHub contribution workflows that follow assume all commits you create are signed-off in this way. ## Preparing for GitHub Pull Request (PR) Contributions First-time contributors that are already familiar with the GitHub flow are encouraged to use the same process for CUE contributions. Even though CUE maintainers use GerritHub for code review, the GitHub PR workflow is 100% supported. Here is a checklist of the steps to follow when contributing via GitHub PR workflow: - **Step 0**: Review the guidelines on [Good Commit Messages](#good-commit-messages), [The Review Process](#the-review-process) and [Miscellaneous Topics](#miscellaneous-topics) - **Step 1**: Create a GitHub account if you do not have one. - **Step 2**: [Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) the CUE project, and clone your fork locally That's it! You are now ready to send a change via GitHub, the subject of the next section. ## Sending a change via GitHub The GitHub documentation around [working with forks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models) is extensive so we will not cover that ground here. Before making any changes it's a good idea to verify that you have a stable baseline by running the tests: ```console $ go test ./... ``` Then make your planned changes and create a commit from the staged changes: ```console # Edit files $ git add file1 file2 $ git commit -s ``` Notice as we explained above, the `-s` flag asserts the Developer Certificate of Origin by adding a `Signed-off-by` line to a commit. When writing a commit message, remember the guidelines on [good commit messages](#good-commit-messages). You’ve written and tested your code, but before sending code out for review, run all the tests from the root of the repository to ensure the changes don’t break other packages or programs: ```console $ go test ./... ``` Your change is now ready! [Submit a PR](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) in the usual way. Once your PR is submitted, a maintainer will trigger continuous integration (CI) workflows to run and [review your proposed change](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request). The results from CI and the review might indicate further changes are required, and this is where the CUE project differs from others: ### Making changes to a PR Some projects accept and encourage multiple commits in a single PR. Either as a way of breaking down the change into smaller parts, or simply as a record of the various changes during the review process. The CUE project follows the Gerrit model of a single commit being the unit of change. Therefore, all PRs must only contain a single commit. But how does this work if you need to make changes requested during the review process? Does this not require you to create additional commits? The easiest way to maintain a single commit is to amend an existing commit. Rather misleadingly, this doesn't actually amend a commit, but instead creates a new commit which is the result of combining the last commit and any new changes: ```console # PR is submitted, feedback received. Time to make some changes! $ git add file1 file2 # stage the files we have added/removed/changed $ git commit --amend # amend the last commit $ git push -f # push the amended commit to your PR ``` The `-f` flag is required to force push your branch to GitHub: this overrides a warning from `git` telling you that GitHub knows nothing about the relationship between the original commit in your PR and the amended commit. What happens if you accidentally create an additional commit and now have two commits on your branch? No worries, you can "squash" commits on a branch to create a single commit. See the GitHub documentation on [how to squash commits with GitHub Desktop](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/managing-commits/squashing-commits), or using the [`git` command interactively](https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec). ### PR approved! With the review cycle complete, the CI checks green and your PR approved, it will be imported into GerritHub and then submitted. Your PR will close automatically as it is "merged" in GerritHub. Congratulations! You will have made your first contribution to the CUE project. ## Preparing for GerritHub [CL](https://google.github.io/eng-practices/#terminology) Contributions CUE maintainers use GerritHub for code review. It has a powerful review interface with comments that are attributed to patchsets (versions of a change). Orienting changes around a single commit allows for "stacked" changes, and also encourages unrelated changes to be broken into separate CLs because the process of creating and linking CLs is so easy. For those more comfortable with contributing via GitHub PRs, please continue to do so: the CUE project supports both workflows so that people have a choice. For those who would like to contribute via GerritHub, read on! ### Overview The first step in the GerritHub flow is registering as a CUE contributor and configuring your environment. Here is a checklist of the required steps to follow: - **Step 0**: Review the guidelines on [Good Commit Messages](#good-commit-messages), [The Review Process](#the-review-process) and [Miscellaneous Topics](#miscellaneous-topics) - **Step 1**: Decide which email address you want to use for contributions. - **Step 2**: Set up a [GerritHub](http://gerrithub.io/) account. - **Step 3**: [Install `git-codereview`](#step-3-install-the-git-codereview-command) - **Step 4**: Clone the CUE repository locally. We cover steps 1-4 in more detail below. ### Step 1: Decide which email address you want to use for contributions A contribution to CUE is made through a specific e-mail address. Make sure to use the same account throughout the process and for all your subsequent contributions. You may need to decide whether to use a personal address or a corporate address. The choice will depend on who will own the copyright for the code that you will be writing and submitting. You might want to discuss this topic with your employer before deciding which account to use. You also need to make sure that your `git` tool is configured to create commits using your chosen e-mail address. You can either configure Git globally (as a default for all projects), or locally (for a single specific project). You can check the current configuration with this command: ```console $ git config --global user.email # check current global config $ git config user.email # check current local config ``` To change the configured address: ```console $ git config --global user.email name@example.com # change global config $ git config user.email name@example.com # change local config ``` ### Step 2: Setup a GerritHub account If you have not used GerritHub before, setting up an account is a simple process: - Visit [GerritHub](http://gerrithub.io/). - Click "First Time Sign In". - Click the green "Sign In" button, to sign in using your GitHub credentials. - When prompted "Which level of GitHub access do you need?", choose "Default" and then click "Login." - Click "Authorize gerritforge-ltd" on the GitHub auth page. - Confirm account profile details and click "Next." If you want to use SSH for authentication *to GerritHub*, SSH keys can be [configured in your user profile](https://review.gerrithub.io/settings/#SSHKeys). If you choose to use SSH for authentication, you will not be able to use the `git-codereview` command that's suggested later in this document, as the command [doesn't support SSH-based git origins](https://github.com/golang/go/issues/9599#issuecomment-70538097). For HTTP Credentials, [generate a password via your user profile](https://review.gerrithub.io/settings/#HTTPCredentials). Then use an existing HTTP authentication mechanism like `.netrc`, macOS KeyChain, or some other [credential helper](https://git-scm.com/docs/gitcredentials). If you have any troubles with this step, please [raise an issue](https://cuelang.org/issues/new). ### Step 3: Install the `git-codereview` command Changes to CUE must be reviewed before they are accepted, no matter who makes the change. A custom `git` command called `git-codereview` simplifies sending changes to Gerrit. Install the `git-codereview` command by running, ```console $ go install golang.org/x/review/git-codereview@master ``` Make sure `git-codereview` is installed in your shell `PATH`, so that the `git` command can find it. Check that ```console $ git codereview help ``` prints help text, not an error. On Windows, when using git-bash you must make sure that `git-codereview.exe` is in your `git` exec-path. Run `git --exec-path` to discover the right location then create a symbolic link or just copy the executable from $GOPATH/bin to this directory. ### Step 4: Clone the CUE repository locally Visit https://review.gerrithub.io/admin/repos/cue-lang/cue, then click "SSH" or "HTTP" depending on which authentication mechanism you configured in step 2. Then copy and run the corresponding "Clone" command. Make sure not to use "ANONYMOUS HTTP", as that will not work with `git-codereview` command. ## Sending a change via GerritHub Sending a change via GerritHub is quite different to the GitHub PR flow. At first the differences might be jarring, but with practice the workflow is incredibly intuitive and far more powerful when it comes to chains of "stacked" changes. ### Step 1: Ensure you have a stable baseline With a working directory of your local clone of the CUE repository, run the tests: ```console $ go test ./... ``` ### Step 2: Prepare changes in a new branch Each CUE change must be made in a branch, created from the `master` branch. You can use the normal `git` commands to create a branch and stage changes: ```console $ git checkout -b mybranch $ [edit files...] $ git add [files...] ``` To commit changes, instead of `git commit -s`, use `git codereview change -s`. ```console $ git codereview change -s (opens $EDITOR) ``` You can edit the commit description in your favorite editor as usual. The `git codereview change` command will automatically add a unique Change-Id line near the bottom. That line is used by Gerrit to match successive uploads of the same change. Do not edit or delete it. A Change-Id looks like this: ``` Change-Id: I2fbdbffb3aab626c4b6f56348861b7909e3e8990 ``` The `git-codereview` command also checks that you've run `go fmt` over the source code, and that the commit message follows the suggested format. If you need to edit the files again, you can stage the new changes and re-run `git codereview change -s`: each subsequent run will amend the existing commit while preserving the Change-Id. Make sure that you always keep a single commit in each branch. If you add more commits by mistake, you can use `git rebase` to [squash them together](https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec) into a single one. ### Step 3: Test your changes You've written and tested your code, but before sending code out for review, run all the tests for the whole tree to ensure the changes don't break other packages or programs: ```console $ go test ./... ``` ### Step 4: Send changes for review Once the change is ready and tested over the whole tree, send it for review. This is done with the `mail` sub-command which, despite its name, doesn't directly mail anything; it just sends the change to Gerrit: ```console $ git codereview mail ``` Gerrit assigns your change a number and URL, which `git codereview mail` will print, something like: ``` remote: New Changes: remote: https://review.gerrithub.io/99999 math: improved Sin, Cos and Tan precision for very large arguments ``` If you get an error instead, see the ["Troubleshooting mail errors"](#troubleshooting-gerrithub-mail-errors). ### Step 5: Revise changes after a review CUE maintainers will review your code on Gerrit, and you will get notifications via e-mail. You can see the review on Gerrit and comment on them there. You can also reply [using e-mail](https://gerrit-review.googlesource.com/Documentation/intro-user.html#reply-by-email) if you prefer. If you need to revise your change after the review, edit the files in the same branch you previously created, add them to the Git staging area, and then amend the commit with `git codereview change`: ```console $ git codereview change # amend current commit (without -s because we already signed-off, above) (open $EDITOR) $ git codereview mail # send new changes to Gerrit ``` If you don't need to change the commit description, just save and exit from the editor. Remember not to touch the special `Change-Id` line. Again, make sure that you always keep a single commit in each branch. If you add more commits by mistake, you can use `git rebase` to [squash them together](https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec) into a single one. ### CL approved! With the review cycle complete, the CI checks green and your CL approved with `+2`, it will be submitted. Congratulations! You will have made your first contribution to the CUE project. ## Good commit messages Commit messages in CUE follow a specific set of conventions, which we discuss in this section. Here is an example of a good one: ``` cue/ast/astutil: fix resolution bugs This fixes several bugs and documentation bugs in identifier resolution. 1. Resolution in comprehensions would resolve identifiers to themselves. 2. Label aliases now no longer bind to references outside the scope of the field. The compiler would catch this invalid bind and report an error, but it is better not to bind in the first place. 3. Remove some more mentions of Template labels. 4. Documentation for comprehensions was incorrect (Scope and Node were reversed). 5. Aliases X in `X=[string]: foo` should only be visible in foo. Fixes #946 ``` ### First line The first line of the change description is conventionally a short one-line summary of the change, prefixed by the primary affected package (`cue/ast/astutil` in the example above). A rule of thumb is that it should be written so to complete the sentence "This change modifies CUE to \_\_\_\_." That means it does not start with a capital letter, is not a complete sentence, and actually summarizes the result of the change. Follow the first line by a blank line. ### Main content The rest of the description elaborates and should provide context for the change and explain what it does. Write in complete sentences with correct punctuation, just like for your comments in CUE. Don't use HTML, Markdown, or any other markup language. ### Referencing issues The special notation `Fixes #12345` associates the change with issue 12345 in the [CUE issue tracker](https://cuelang.org/issue/12345) When this change is eventually applied, the issue tracker will automatically mark the issue as fixed. If the change is a partial step towards the resolution of the issue, uses the notation `Updates #12345`. This will leave a comment in the issue linking back to the change in Gerrit, but it will not close the issue when the change is applied. All issues are tracked in the main repository's issue tracker. If you are sending a change against a subrepository, you must use the fully-qualified syntax supported by GitHub to make sure the change is linked to the issue in the main repository, not the subrepository (eg. `Fixes cue-lang/cue#999`). ## The review process This section explains the review process in detail and how to approach reviews after a change has been sent to either GerritHub or GitHub. ### Common mistakes When a change is sent to Gerrit, it is usually triaged within a few days. A maintainer will have a look and provide some initial review that for first-time contributors usually focuses on basic cosmetics and common mistakes. These include things like: - Commit message not following the suggested format. - The lack of a linked GitHub issue. The vast majority of changes require a linked issue that describes the bug or the feature that the change fixes or implements, and consensus should have been reached on the tracker before proceeding with it. Gerrit reviews do not discuss the merit of the change, just its implementation. Only trivial or cosmetic changes will be accepted without an associated issue. ### Continuous Integration (CI) checks After an initial reading of your change, maintainers will trigger CI checks, that run a full test suite and [Unity](https://cuelabs.dev/unity/) checks. Most CI tests complete in a few minutes, at which point a link will be posted in Gerrit where you can see the results, or if you are submitting a PR results are presented as checks towards the bottom of the PR. If any of the CI checks fail, follow the link and check the full logs. Try to understand what broke, update your change to fix it, and upload again. Maintainers will trigger a new CI run to see if the problem was fixed. ### Reviews The CUE community values very thorough reviews. Think of each review comment like a ticket: you are expected to somehow "close" it by acting on it, either by implementing the suggestion or convincing the reviewer otherwise. After you update the change, go through the review comments and make sure to reply to every one. In GerritHub you can click the "Done" button to reply indicating that you've implemented the reviewer's suggestion and in GitHub you can mark a comment as resolved; otherwise, click on "Reply" and explain why you have not, or what you have done instead. It is perfectly normal for changes to go through several round of reviews, with one or more reviewers making new comments every time and then waiting for an updated change before reviewing again. This cycle happens even for experienced contributors, so don't be discouraged by it. ### Voting conventions in GerritHub As they near a decision, reviewers will make a "vote" on your change. The Gerrit voting system involves an integer in the range -2 to +2: - **+2** The change is approved for being merged. Only CUE maintainers can cast a +2 vote. - **+1** The change looks good, but either the reviewer is requesting minor changes before approving it, or they are not a maintainer and cannot approve it, but would like to encourage an approval. - **-1** The change is not good the way it is but might be fixable. A -1 vote will always have a comment explaining why the change is unacceptable. - **-2** The change is blocked by a maintainer and cannot be approved. Again, there will be a comment explaining the decision. ### Reviewed changed in GitHub When reviewing a PR, a reviewer will indicate the nature of their response: * **Comments** - general feedback without explicit approval. * **Approve** - feedback and approval for this PR to accepted and submitted in GerritHub. * **Request changes** - feedback that must be addressed before this PR can proceed. ### Submitting an approved change After the code has been `+2`'ed in GerritHub or "Approved" in GitHub, an approver will apply it to the `master` branch using the Gerrit user interface. This is called "submitting the change". The two steps (approving and submitting) are separate because in some cases maintainers may want to approve it but not to submit it right away (for instance, the tree could be temporarily frozen). Submitting a change checks it into the repository. The change description will include a link to the code review, which will be updated with a link to the change in the repository. Since the method used to integrate the changes is Git's "Cherry Pick", the commit hashes in the repository will be changed by the submit operation. If your change has been approved for a few days without being submitted, feel free to write a comment in GerritHub or GitHub requesting submission. ## Miscellaneous topics This section collects a number of other comments that are outside the issue/edit/code review/submit process itself. ### Copyright headers Files in the CUE repository don't list author names, both to avoid clutter and to avoid having to keep the lists up to date. Instead, your name will appear in the [git change log](https://review.gerrithub.io/plugins/gitiles/cue-lang/cue/+log) and in [GitHub's contributor stats](https://github.com/cue-lang/cue/graphs/contributors) when using an email address linked to a GitHub account. New files that you contribute should use the standard copyright header with the current year reflecting when they were added. Do not update the copyright year for existing files that you change. ``` // Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. ``` ### Troubleshooting GerritHub mail errors The most common way that the `git codereview mail` command fails is because the e-mail address in the commit does not match the one that you used during the registration process. If you see something like... ``` remote: Processing changes: refs: 1, done remote: remote: ERROR: In commit ab13517fa29487dcf8b0d48916c51639426c5ee9 remote: ERROR: author email address your.email@domain.com remote: ERROR: does not match your user account. ``` you need to configure Git for this repository to use the e-mail address that you registered with. To change the e-mail address to ensure this doesn't happen again, run: ```console $ git config user.email email@address.com ``` Then change the commit to use this alternative e-mail address with this command: ```console $ git commit --amend --author="Author Name <email@address.com>" ``` Then retry by running: ```console $ git codereview mail ``` ### Quickly testing your changes Running `go test ./...` for every single change to the code tree is burdensome. Even though it is strongly suggested to run it before sending a change, during the normal development cycle you may want to compile and test only the package you are developing. In this section, we'll call the directory into which you cloned the CUE repository `$CUEDIR`. As CUE uses Go modules, The `cue` tool built by `go install` will be installed in the `bin/go` in your home directory by default. If you're changing the CUE APIs or code, you can test the results in just this package directory. ```console $ cd $CUEDIR/cue $ [make changes...] $ go test ``` You don't need to build a new cue tool to test it. Instead you can run the tests from the root. ```console $ cd $CUEDIR $ go test ./... ``` To use the new tool you would still need to build and install it. ### Specifying a reviewer / CCing others in GerritHub You can specify a reviewer or CC interested parties using the `-r` or `-cc` options. Both accept a comma-separated list of e-mail addresses: ```console $ git codereview mail -r joe@cuelang.org -cc mabel@example.com,math-nuts@swtch.com ``` ### Synchronize your client with GerritHub While you were working, others might have submitted changes to the repository. To update your local branch, run ```console $ git codereview sync ``` (Under the covers this runs `git pull -r`.) ### Reviewing code by others As part of the review process reviewers can propose changes directly (in the GitHub workflow this would be someone else attaching commits to a pull request). You can import these changes proposed by someone else into your local Git repository. On the Gerrit review page, click the "Download ▼" link in the upper right corner, copy the "Checkout" command and run it from your local Git repo. It will look something like this: ```console $ git fetch https://review.gerrithub.io/a/cue-lang/cue refs/changes/67/519567/1 && git checkout FETCH_HEAD ``` To revert, change back to the branch you were working in. ### Set up git aliases The `git-codereview` command can be run directly from the shell by typing, for instance, ```console $ git codereview sync ``` but it is more convenient to set up aliases for `git-codereview`'s own subcommands, so that the above becomes, ```console $ git sync ``` The `git-codereview` subcommands have been chosen to be distinct from Git's own, so it's safe to define these aliases. To install them, copy this text into your Git configuration file (usually `.gitconfig` in your home directory): ``` [alias] change = codereview change gofmt = codereview gofmt mail = codereview mail pending = codereview pending submit = codereview submit sync = codereview sync ``` ### Sending multiple dependent changes Advanced users may want to stack up related commits in a single branch. Gerrit allows for changes to be dependent on each other, forming such a dependency chain. Each change will need to be approved and submitted separately but the dependency will be visible to reviewers. To send out a group of dependent changes, keep each change as a different commit under the same branch, and then run: ```console $ git codereview mail HEAD ``` Make sure to explicitly specify `HEAD`, which is usually not required when sending single changes. This is covered in more detail in [the Gerrit documentation](https://gerrit-review.googlesource.com/Documentation/concept-changes.html). ### Do I really have to add the `-s` flag to each commit? Earlier in this guide we explained the role the [Developer Certificate of Origin](https://developercertificate.org/) plays in contributions to the CUE project. we also explained how `git commit -s` can be used to sign-off each commit. But: * it's easy to forget the `-s` flag; * it's not always possible/easy to fix up other tools that wrap the `git commit` step. You can automate the sign-off step using a [`git` hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). Run the following commands in the root of a `git` repository where you want to automatically sign-off each commit: ``` cat <<'EOD' > .git/hooks/prepare-commit-msg #!/bin/sh NAME=$(git config user.name) EMAIL=$(git config user.email) if [ -z "$NAME" ]; then echo "empty git config user.name" exit 1 fi if [ -z "$EMAIL" ]; then echo "empty git config user.email" exit 1 fi git interpret-trailers --if-exists doNothing --trailer \ "Signed-off-by: $NAME <$EMAIL>" \ --in-place "$1" EOD chmod +x .git/hooks/prepare-commit-msg ``` If you already have a `prepare-commit-msg` hook, adapt it accordingly. The `-s` flag will now be implied every time a commit is created. ## Code of Conduct Guidelines for participating in CUE community spaces and a reporting process for handling issues can be found in the [Code of Conduct](https://cuelang.org/docs/contribution_guidelines/conduct). cue-lang-cue-db9cc73/LICENSE000066400000000000000000000261361474664451600155150ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. cue-lang-cue-db9cc73/README.md000066400000000000000000000102231474664451600157550ustar00rootroot00000000000000 [![Go Reference](https://pkg.go.dev/badge/cuelang.org/go.svg)](https://pkg.go.dev/cuelang.org/go) [![Documentation](https://img.shields.io/badge/CUE-Docs-0066ff)](https://cuelang.org/docs/) [![Github](https://github.com/cue-lang/cue/actions/workflows/trybot.yaml/badge.svg)](https://github.com/cue-lang/cue/actions/workflows/trybot.yaml?query=branch%3Amaster+event%3Apush) [![Go 1.22+](https://img.shields.io/badge/go-1.22-9cf.svg)](https://golang.org/dl/) [![platforms](https://img.shields.io/badge/platforms-linux|windows|macos-inactive.svg)]() [![Docker Image](https://img.shields.io/docker/v/cuelang/cue?sort=semver&label=docker)](https://hub.docker.com/r/cuelang/cue) # CUE - _Configure, Unify, Execute_ CUE makes it easy to validate data, write schemas, and ensure configurations align with policies. CUE works with a wide range of tools and formats that you're already using such as Go, JSON, YAML, OpenAPI, and JSON Schema. For more information and documentation, including __tutorials and guides__, see [cuelang.org](https://cuelang.org). ### Download and Install The full range of installation methods for the `cue` command are listed on the [cuelang.org site](https://cuelang.org/docs/introduction/installation/), including the official container image suitable for use with Docker. Here are two common ways to install the command: #### Release builds Download the [latest release](https://github.com/cue-lang/cue/releases/latest/) from GitHub. #### Install from Source You need [Go 1.22 or later](https://go.dev/doc/install) to install CUE from source: go install cuelang.org/go/cmd/cue@latest You can also clone the repository and build it directly via `go install ./cmd/cue`. Note that local builds [lack version information](https://go.dev/issue/50603), so you should inject the version string when building a release, such as: git switch -d v0.11.0 go install -ldflags='-X cuelang.org/go/cmd/cue/cmd.version=v0.11.0' ./cmd/cue ### Learning CUE The fastest way to learn the basics is to follow the [tour on the website](https://cuelang.org/docs/tour/). More documentation including various tutorials can be found [on the website](https://cuelang.org/docs/). ### References - [Language Specification](https://cuelang.org/docs/reference/spec/): the official CUE Language specification - [Go API](https://pkg.go.dev/cuelang.org/go/cue): the Go API on pkg.go.dev - [Builtin packages](https://pkg.go.dev/cuelang.org/go/pkg): builtin functions available from CUE programs - [`cue` CLI](https://cuelang.org/docs/reference/cli/): the `cue` command line interface ### Go release support policy As a general rule, we support the two most recent major releases of Go, matching Go's [security policy](https://go.dev/doc/security/policy). For example, if CUE v0.7.0 is released when Go's latest version is 1.21.5, v0.7.x including any following bugfix releases will require Go 1.20 or later. ### Contributing To contribute, please read the [Contribution Guide](CONTRIBUTING.md). ## Code of Conduct Guidelines for participating in CUE community spaces and a reporting process for handling issues can be found in the [Code of Conduct](https://cuelang.org/docs/reference/code-of-conduct/). ## Contact - Ask questions via [GitHub Discussions](https://github.com/cue-lang/cue/discussions) - Chat with us on [Slack](https://cuelang.org/s/slack) and [Discord](https://cuelang.org/s/discord) - Subscribe to our [Community Calendar](https://cuelang.org/s/community-calendar) for community updates, demos, office hours, etc --- Unless otherwise noted, the CUE source files are distributed under the Apache 2.0 license found in the LICENSE file. cue-lang-cue-db9cc73/cmd/000077500000000000000000000000001474664451600152435ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/000077500000000000000000000000001474664451600160175ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/Dockerfile000066400000000000000000000001271474664451600200110ustar00rootroot00000000000000FROM gcr.io/distroless/static:latest COPY cue /usr/bin/cue ENTRYPOINT ["/usr/bin/cue"] cue-lang-cue-db9cc73/cmd/cue/cmd/000077500000000000000000000000001474664451600165625ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/add.go000066400000000000000000000153161474664451600176470ustar00rootroot00000000000000// Copyright 2019 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "errors" "fmt" "io" "os" "path/filepath" "strings" "text/template" "github.com/spf13/cobra" "cuelang.org/go/cue" "cuelang.org/go/cue/build" "cuelang.org/go/cue/format" "cuelang.org/go/cue/load" "cuelang.org/go/cue/parser" ) func newAddCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ // TODO: this command is still experimental, don't show it in // the documentation just yet. Hidden: true, Use: "add [--list]", Short: "bulk append to CUE files", Long: `Append a common snippet of CUE to many files and commit atomically. `, RunE: mkRunE(c, runAdd), } f := cmd.Flags() f.Bool(string(flagList), false, "text executed as Go template with instance info") f.BoolP(string(flagDryRun), "n", false, "only run simulation") f.StringP(string(flagPackage), "p", "", "package to append to") return cmd } func runAdd(cmd *Command, args []string) (err error) { return doAdd(cmd, args) } func doAdd(cmd *Command, args []string) (err error) { // Offsets at which to restore original files, if any, if any of the // appends fail. // Ideally this is placed below where it is used, but we want to make // absolutely sure that the error variable used in defer is the named // returned value and not some shadowed value. originals := []originalFile{} defer func() { if err != nil { restoreOriginals(cmd, originals) } }() // build instance cache builds := map[string]*build.Instance{} getBuild := func(path string) *build.Instance { if b, ok := builds[path]; ok { return b } b := load.Instances([]string{path}, nil)[0] builds[path] = b return b } // determine file set. todo := []*fileInfo{} done := map[string]bool{} for _, arg := range args { dir, base := filepath.Split(arg) dir = filepath.Clean(dir) matches, err := filepath.Glob(dir) if err != nil { return err } for _, m := range matches { if fi, err := os.Stat(m); err != nil || !fi.IsDir() { continue } file := filepath.Join(m, base) if done[file] { continue } if s := filepath.ToSlash(file); strings.HasPrefix(s, "pkg/") || strings.Contains(s, "/pkg/") { continue } done[file] = true fi, err := initFile(cmd, file, getBuild) if err != nil { return err } todo = append(todo, fi) b := fi.build if flagList.Bool(cmd) && (b == nil) { return fmt.Errorf("instance info not available for %s", fi.filename) } } } // Read text to be appended. text, err := io.ReadAll(cmd.InOrStdin()) if err != nil { return err } var tmpl *template.Template if flagList.Bool(cmd) { tmpl, err = template.New("append").Parse(string(text)) if err != nil { return err } } for _, fi := range todo { if tmpl == nil { fi.contents.Write(text) continue } if err := tmpl.Execute(fi.contents, fi.build); err != nil { return err } } if flagDryRun.Bool(cmd) { stdout := cmd.OutOrStdout() for _, fi := range todo { fmt.Fprintln(stdout, "---", fi.filename) _, _ = io.Copy(stdout, fi.contents) } return nil } // All verified. Execute the todo plan for _, fi := range todo { fo, err := fi.appendAndCheck() if err != nil { return err } originals = append(originals, fo) } // Verify resulting builds for _, fi := range todo { builds = map[string]*build.Instance{} b := getBuild(fi.buildArg) if b.Err != nil { return b.Err } i := cue.Build([]*build.Instance{b})[0] if i.Err != nil { return i.Err } if err := i.Value().Validate(); err != nil { return i.Err } } return nil } type originalFile struct { filename string contents []byte } func restoreOriginals(cmd *Command, originals []originalFile) { for _, fo := range originals { if err := fo.restore(); err != nil { fmt.Fprintln(cmd.Stderr(), "Error restoring file: ", err) } } } func (fo *originalFile) restore() error { if len(fo.contents) == 0 { return os.Remove(fo.filename) } return os.WriteFile(fo.filename, fo.contents, 0666) } type fileInfo struct { filename string buildArg string contents *bytes.Buffer build *build.Instance } func initFile(cmd *Command, file string, getBuild func(path string) *build.Instance) (todo *fileInfo, err error) { defer func() { if err != nil { err = fmt.Errorf("init file: %v", err) } }() dir := filepath.Dir(file) todo = &fileInfo{file, dir, &bytes.Buffer{}, nil} if fi, err := os.Stat(file); err != nil { if !os.IsNotExist(err) { return nil, err } // File does not exist b := getBuild(dir) todo.build = b pkg := flagPackage.String(cmd) if pkg != "" { // TODO: do something more intelligent once the package name is // computed on a module basis, even for empty directories. b.PkgName = pkg b.Err = nil } else { pkg = b.PkgName } if pkg == "" { return nil, errors.New("must specify package using -p for new files") } todo.buildArg = file fmt.Fprintf(todo.contents, "package %s\n\n", pkg) } else { if fi.IsDir() { return nil, fmt.Errorf("cannot append to directory %s", file) } f, err := parser.ParseFile(file, nil) if err != nil { return nil, err } if pkgName := f.PackageName(); pkgName != "" { if pkg := flagPackage.String(cmd); pkg != "" && pkgName != pkg { return nil, fmt.Errorf("package mismatch (%s vs %s) for file %s", pkgName, pkg, file) } todo.build = getBuild(dir) } else { if pkg := flagPackage.String(cmd); pkg != "" { return nil, fmt.Errorf("file %s has no package clause but package %s requested", file, pkg) } todo.build = getBuild(file) todo.buildArg = file } } return todo, nil } func (fi *fileInfo) appendAndCheck() (fo originalFile, err error) { // Read original file b, err := os.ReadFile(fi.filename) if err == nil { fo.filename = fi.filename fo.contents = b } else if !os.IsNotExist(err) { return originalFile{}, err } if !bytes.HasSuffix(b, []byte("\n")) { b = append(b, '\n') } b = append(b, fi.contents.Bytes()...) b, err = format.Source(b) if err != nil { return originalFile{}, err } if err = os.WriteFile(fi.filename, b, 0666); err != nil { // Just in case, attempt to restore original file. _ = fo.restore() return originalFile{}, err } return fo, nil } cue-lang-cue-db9cc73/cmd/cue/cmd/cmd.go000066400000000000000000000111521474664451600176540ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "cuelang.org/go/cue/errors" "github.com/spf13/cobra" ) // TODO: generate long description from documentation. func newCmdCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "cmd [inputs]", Short: "run a user-defined workflow command", Long: `cmd executes the named command for each of the named instances. Workflow commands define actions on instances. For example, they may specify how to upload a configuration to Kubernetes. Workflow commands are defined directly in tool files, which are regular CUE files within the same package with a filename ending in _tool.cue. These are typically defined at the module root so that they apply to all instances. Each command consists of one or more tasks. A task may, for example, load or write a file, consult a user on the command line, fetch a web page, and so on. Each task has inputs and outputs. Outputs are typically filled out by the task implementation as the task completes. Inputs of tasks my refer to outputs of other tasks. The cue tool does a static analysis of the configuration and only starts tasks that are fully specified. Upon completion of each task, cue rewrites the instance, filling in the completed task, and reevaluates which other tasks can now start, and so on until all tasks have completed. Available tasks can be found in the package documentation at https://pkg.go.dev/cuelang.org/go/pkg/tool?tab=subdirectories Examples: In this simple example, we define a workflow command called "hello", which declares a single task called "print" which uses "tool/exec.Run" to execute a shell command that echos output to the terminal: $ cat < hello_tool.cue package foo import "tool/exec" city: "Amsterdam" who: *"World" | string @tag(who) // Say hello! command: hello: { print: exec.Run & { cmd: "echo Hello \(who)! Welcome to \(city)." } } EOF We run the "hello" workflow command like this: $ cue cmd hello Hello World! Welcome to Amsterdam. $ cue cmd --inject who=Jan hello Hello Jan! Welcome to Amsterdam. In this example we declare the "prompted" workflow command which has four tasks. The first task prompts the user for a string input. The second task depends on the first, and echos the response back to the user with a friendly message. The third task pipes the output from the second to a file. The fourth task pipes the output from the second to standard output (i.e. it echos it again). package foo import ( "tool/cli" "tool/exec" "tool/file" ) city: "Amsterdam" // Say hello! command: prompter: { // save transcript to this file var: file: *"out.txt" | string @tag(file) ask: cli.Ask & { prompt: "What is your name?" response: string } // starts after ask echo: exec.Run & { cmd: ["echo", "Hello", ask.response + "!"] stdout: string // capture stdout } // starts after echo append: file.Append & { filename: var.file contents: echo.stdout } // also starts after echo print: cli.Print & { text: echo.stdout } } Run "cue help commands" for more details on tasks and workflow commands. `, RunE: mkRunE(c, func(cmd *Command, args []string) error { if len(args) == 0 { w := cmd.OutOrStderr() fmt.Fprintln(w, "cmd must be run as one of its subcommands") fmt.Fprintln(w, "Run 'cue help cmd' for known subcommands.") return ErrPrintedError } tools, err := buildTools(cmd, args[1:]) if err != nil { return err } sub, err := customCommand(cmd, commandSection, args[0], tools) if err != nil { w := cmd.OutOrStderr() fmt.Fprint(w, errors.Details(err, &errors.Config{Cwd: rootWorkingDir})) fmt.Fprintln(w, `Ensure custom commands are defined in a "_tool.cue" file.`) fmt.Fprintln(w, "Run 'cue help cmd' to list available custom commands.") return ErrPrintedError } // Presumably the *cobra.Command argument should be cmd.Command, // as that is the one which will have the right settings applied. return sub.RunE(cmd.Command, args[1:]) }), } addInjectionFlags(cmd.Flags(), true, false) return cmd } cue-lang-cue-db9cc73/cmd/cue/cmd/common.go000066400000000000000000000465531474664451600204160ustar00rootroot00000000000000// Copyright 2018 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "cmp" "os" "path/filepath" "regexp" "strings" "github.com/spf13/pflag" "golang.org/x/text/language" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/load" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" ) var requestedVersion = os.Getenv("CUE_SYNTAX_OVERRIDE") func defaultConfig() (*config, error) { reg, err := getCachedRegistry() if err != nil { return nil, err } return &config{ loadCfg: &load.Config{ ParseFile: func(name string, src interface{}) (*ast.File, error) { version := internal.APIVersionSupported if requestedVersion != "" { switch { case strings.HasPrefix(requestedVersion, "v0.1"): version = -1000 + 100 } } options := []parser.Option{ parser.FromVersion(version), parser.ParseComments, } // TODO: consolidate all options into a single CUE_DEBUG variable. if os.Getenv("CUE_DEBUG_PARSER_TRACE") != "" { options = append(options, parser.Trace) } return parser.ParseFile(name, src, options...) }, Registry: reg, }, }, nil } func getLang() language.Tag { loc := cmp.Or(os.Getenv("LC_ALL"), os.Getenv("LANG")) loc, _, _ = strings.Cut(loc, ".") return language.Make(loc) } func loadFromArgs(args []string, cfg *load.Config) []*build.Instance { binst := load.Instances(args, cfg) if len(binst) == 0 { return nil } return binst } // A buildPlan defines what should be done based on command line // arguments and flags. // // TODO: allow --merge/-m to mix in other packages. type buildPlan struct { cmd *Command insts []*build.Instance // instance is a pre-compiled instance, which exists if value files are // being processed, which may require a schema to decode. instance *instance cfg *config // If orphanFiles are mixed with CUE files and/or if placement flags are used, // the instance is also included in insts. importing bool mergeData bool // do not merge individual data files. orphaned []*decoderInfo orphanInstance *build.Instance // imported files are files that were orphaned in the build instance, but // were placed in the instance by using one the --files, --list or --path // flags. imported []*ast.File expressions []ast.Expr // only evaluate these expressions within results schema ast.Expr // selects schema in instance for orphaned values // orphan placement flags. perFile bool useList bool path []ast.Label useContext bool // outFile defines the file to output to. Default is CUE stdout. outFile *build.File encConfig *encoding.Config } // instances iterates either over a list of instances, or a list of // data files. In the latter case, there must be either 0 or 1 other // instance, with which the data instance may be merged. func (b *buildPlan) instances() iterator { var i iterator switch { case len(b.orphaned) > 0: i = newStreamingIterator(b) case len(b.insts) > 0: insts, err := buildInstances(b.cmd, b.insts, false) i = &instanceIterator{ inst: b.instance, a: insts, e: err, i: -1, } case b.instance != nil: i = &instanceIterator{ a: []*instance{b.instance}, i: -1, } b.instance = nil default: // No instances; return an iterator with zero values. // This can happen when the input is an empty jsonl file, for example. // Zero iteration may not make much sense in some scenarios like export, // but an empty jsonl file is valid, so doing nothing seems reasonable. i = &instanceIterator{} } if len(b.expressions) > 0 { return &expressionIter{ iter: i, expr: b.expressions, i: len(b.expressions), } } return i } type iterator interface { scan() bool value() cue.Value file() *ast.File // may return nil err() error close() id() string // may return "" } type instance struct { id string err error val cue.Value } func (i *instance) Value() cue.Value { return i.val } type instanceIterator struct { inst *instance a []*instance i int e error } func (i *instanceIterator) scan() bool { i.i++ return i.i < len(i.a) && i.e == nil } func (i *instanceIterator) close() {} func (i *instanceIterator) err() error { return i.e } func (i *instanceIterator) value() cue.Value { v := i.a[i.i].Value() if i.inst != nil { v = v.Unify(i.inst.Value()) } return v } func (i *instanceIterator) file() *ast.File { return nil } func (i *instanceIterator) id() string { if i.i > len(i.a) { return "" } return i.a[i.i].id } type streamingIterator struct { b *buildPlan cfg *encoding.Config a []*decoderInfo dec *encoding.Decoder v cue.Value f *ast.File e error } func newStreamingIterator(b *buildPlan) *streamingIterator { i := &streamingIterator{ cfg: b.encConfig, a: b.orphaned, b: b, } return i } func (i *streamingIterator) file() *ast.File { return i.f } func (i *streamingIterator) value() cue.Value { return i.v } func (i *streamingIterator) id() string { return "" } func (i *streamingIterator) scan() bool { if i.e != nil { return false } // advance to next value if i.dec != nil && !i.dec.Done() { i.dec.Next() if i.e = i.dec.Err(); i.e != nil { return false } } // advance to next stream if necessary for i.dec == nil || i.dec.Done() { if i.dec != nil { i.dec.Close() i.dec = nil } if len(i.a) == 0 { return false } i.dec = i.a[0].dec(i.b) if i.e = i.dec.Err(); i.e != nil { return false } i.a = i.a[1:] } // compose value i.f = i.dec.File() v := i.b.cmd.ctx.BuildFile(i.f) if err := v.Err(); err != nil { i.e = err return false } i.v = v if schema := i.b.encConfig.Schema; schema.Exists() { i.v = i.v.Unify(schema) // TODO(required fields): don't merge in schema i.e = i.v.Err() if i.e != nil { if err := i.v.Validate(); err != nil { // Validate should always be non-nil, but just in case. i.e = err } } i.f = nil } return i.e == nil } func (i *streamingIterator) close() { if i.dec != nil { i.dec.Close() i.dec = nil } } func (i *streamingIterator) err() error { if i.dec != nil { if err := i.dec.Err(); err != nil { return err } } return i.e } type expressionIter struct { iter iterator expr []ast.Expr i int } func (i *expressionIter) err() error { return i.iter.err() } func (i *expressionIter) close() { i.iter.close() } func (i *expressionIter) id() string { return i.iter.id() } func (i *expressionIter) scan() bool { i.i++ if i.i < len(i.expr) { return true } if !i.iter.scan() { return false } i.i = 0 return true } func (i *expressionIter) file() *ast.File { return nil } func (i *expressionIter) value() cue.Value { if len(i.expr) == 0 { return i.iter.value() } v := i.iter.value() return v.Context().BuildExpr(i.expr[i.i], cue.Scope(v), cue.InferBuiltins(true), cue.ImportPath(i.iter.id()), ) } type config struct { mode filetypes.Mode fileFilter string reFile *regexp.Regexp encoding build.Encoding interpretation build.Interpretation overrideDefault bool noMerge bool // do not merge individual data files. loadCfg *load.Config } func newBuildPlan(cmd *Command, cfg *config) (p *buildPlan, err error) { var defCfg *config if cfg == nil || cfg.loadCfg == nil { var err error defCfg, err = defaultConfig() if err != nil { return nil, err } } if cfg == nil { cfg = defCfg } if cfg.loadCfg == nil { cfg.loadCfg = defCfg.loadCfg } cfg.loadCfg.Stdin = cmd.InOrStdin() p = &buildPlan{ cfg: cfg, cmd: cmd, importing: cfg.loadCfg.DataFiles, } if err := p.parseFlags(); err != nil { return nil, err } re, err := regexp.Compile(p.cfg.fileFilter) if err != nil { return nil, err } cfg.reFile = re setTags(cfg.loadCfg, cmd.Flags()) return p, nil } func (p *buildPlan) matchFile(file string) bool { return p.cfg.reFile.MatchString(file) } func setTags(cfg *load.Config, flags *pflag.FlagSet) { tags, _ := flags.GetStringArray(string(flagInject)) cfg.Tags = append(cfg.Tags, tags...) if b, _ := flags.GetBool(string(flagInjectVars)); b { cfg.TagVars = load.DefaultTagVars() } } type decoderInfo struct { file *build.File d *encoding.Decoder // may be nil if delayed } func (d *decoderInfo) dec(b *buildPlan) *encoding.Decoder { if d.d == nil { d.d = encoding.NewDecoder(b.cmd.ctx, d.file, b.encConfig) } return d.d } // getDecoders takes the orphaned files of the given instance and splits them in // schemas and values, saving the build.File and encoding.Decoder in the // returned slices. It is up to the caller to Close any of the decoders that are // returned. func (p *buildPlan) getDecoders(b *build.Instance) (schemas, values []*decoderInfo, err error) { files := b.OrphanedFiles if p.cfg.overrideDefault { files = append(files, b.UnknownFiles...) } for _, f := range files { if !b.User && !p.matchFile(f.Filename) { continue } if p.cfg.overrideDefault { f.Encoding = p.cfg.encoding f.Interpretation = p.cfg.interpretation } switch f.Encoding { case build.Protobuf, build.YAML, build.TOML, build.JSON, build.JSONL, build.Text, build.Binary: if f.Interpretation == build.ProtobufJSON { // Need a schema. values = append(values, &decoderInfo{f, nil}) continue } case build.TextProto: if p.importing { return schemas, values, errors.Newf(token.NoPos, "cannot import textproto files") } // Needs to be decoded after any schema. values = append(values, &decoderInfo{f, nil}) continue default: return schemas, values, errors.Newf(token.NoPos, "unsupported encoding %q", f.Encoding) } // We add the module root to the path if there is a module defined. c := *p.encConfig if b.Module != "" { c.ProtoPath = append(c.ProtoPath, b.Root) } d := encoding.NewDecoder(p.cmd.ctx, f, &c) fi, err := filetypes.FromFile(f, p.cfg.mode) if err != nil { return schemas, values, err } switch { // case !fi.Schema: // TODO: value/schema/auto // values = append(values, d) case fi.Form != build.Schema && fi.Form != build.Final: values = append(values, &decoderInfo{f, d}) case f.Interpretation != build.Auto: schemas = append(schemas, &decoderInfo{f, d}) case d.Interpretation() == "": values = append(values, &decoderInfo{f, d}) default: schemas = append(schemas, &decoderInfo{f, d}) } } return schemas, values, nil } // importFiles imports orphan files for existing instances. Note that during // import, both schemas and non-schemas are placed (TODO: should we allow schema // mode here as well? It seems that the existing package should have enough // typing to allow for schemas). // // It is a separate call to allow closing decoders between processing each // package. func (p *buildPlan) importFiles(b *build.Instance) error { // TODO: assume textproto is imported at top-level or just ignore them. schemas, values, err := p.getDecoders(b) if err != nil { return err } return p.placeOrphans(b, append(schemas, values...)) } func parseArgs(cmd *Command, args []string, cfg *config) (p *buildPlan, err error) { p, err = newBuildPlan(cmd, cfg) if err != nil { return nil, err } builds := loadFromArgs(args, cfg.loadCfg) if builds == nil { return nil, errors.Newf(token.NoPos, "invalid args") } if err := p.parsePlacementFlags(); err != nil { return nil, err } for _, b := range builds { if b.Err != nil { return nil, suggestModCommand(b.Err) } switch { case !b.User: if p.importing { if err := p.importFiles(b); err != nil { return nil, err } } p.insts = append(p.insts, b) case p.orphanInstance != nil: return nil, errors.Newf(token.NoPos, "builds contain two file packages") default: p.orphanInstance = b } } if len(p.insts) == 0 && flagGlob.String(p.cmd) != "" { return nil, errors.Newf(token.NoPos, "use of -n/--name flag without a directory") } if b := p.orphanInstance; b != nil { schemas, values, err := p.getDecoders(b) if err != nil { return nil, err } if values == nil { values, schemas = schemas, values } for _, di := range schemas { d := di.dec(p) for ; !d.Done(); d.Next() { if err := b.AddSyntax(d.File()); err != nil { return nil, err } } if err := d.Err(); err != nil { return nil, err } d.Close() } if len(p.insts) > 1 && p.schema != nil { return nil, errors.Newf(token.NoPos, "cannot use --schema/-d with flag more than one schema") } var schema *build.Instance switch n := len(p.insts); n { default: return nil, errors.Newf(token.NoPos, "too many packages defined (%d) in combination with files", n) case 1: if len(schemas) > 0 { return nil, errors.Newf(token.NoPos, "cannot combine packages with individual schema files") } schema = p.insts[0] p.insts = nil case 0: bb := *b schema = &bb b.BuildFiles = nil b.Files = nil } if schema != nil && len(schema.Files) > 0 { // TODO: ignore errors here for now until reporting of concreteness // of errors is correct. // See https://github.com/cue-lang/cue/issues/1483. insts, err := buildInstances( p.cmd, []*build.Instance{schema}, true) if err != nil { return nil, err } inst := insts[0] if err := inst.err; err != nil { return nil, err } p.instance = inst p.encConfig.Schema = inst.Value() if p.schema != nil { v := cmd.ctx.BuildExpr(p.schema, cue.InferBuiltins(true), cue.Scope(inst.Value())) // Note that we don't check v.Err as we don't care about // incomplete errors. if err := v.Validate(); err != nil { return nil, err } p.encConfig.Schema = v } } else if p.schema != nil { return nil, errors.Newf(token.NoPos, "-d/--schema flag specified without a schema") } switch { default: fallthrough case p.schema != nil: p.orphaned = values case p.mergeData, p.usePlacement(), p.importing: if err = p.placeOrphans(b, values); err != nil { return nil, err } } if len(b.Files) > 0 { p.insts = append(p.insts, b) } } if len(p.expressions) > 1 { p.encConfig.Stream = true } return p, nil } func (b *buildPlan) parseFlags() (err error) { b.mergeData = !b.cfg.noMerge && flagMerge.Bool(b.cmd) b.encConfig = &encoding.Config{ Mode: b.cfg.mode, Stdin: b.cmd.InOrStdin(), Stdout: b.cmd.OutOrStdout(), ProtoPath: flagProtoPath.StringArray(b.cmd), AllErrors: flagAllErrors.Bool(b.cmd), PkgName: flagPackage.String(b.cmd), Strict: flagStrict.Bool(b.cmd), } // For commands with an output mode, like `cue export` or `cue def`. if b.cfg.mode != filetypes.Input { out := flagOut.String(b.cmd) outFile := flagOutFile.String(b.cmd) if strings.Contains(out, ":") && strings.Contains(outFile, ":") { return errors.Newf(token.NoPos, "cannot specify qualifier in both --out and --outfile") } if outFile == "" { outFile = "-" } if out != "" { outFile = out + ":" + outFile } b.outFile, err = filetypes.ParseFile(outFile, b.cfg.mode) if err != nil { return err } for _, e := range flagExpression.StringArray(b.cmd) { expr, err := parser.ParseExpr("--expression", e) if err != nil { return err } b.expressions = append(b.expressions, expr) } b.encConfig.Force = flagForce.Bool(b.cmd) } if s := flagSchema.String(b.cmd); s != "" { b.schema, err = parser.ParseExpr("--schema", s) if err != nil { return err } } if s := flagGlob.String(b.cmd); s != "" { // Set a default file filter to only include json and yaml files b.cfg.fileFilter = s } // These flags exist only in specific output modes. switch b.cfg.mode { case filetypes.Export: b.encConfig.EscapeHTML = flagEscape.Bool(b.cmd) case filetypes.Def: b.encConfig.InlineImports = flagInlineImports.Bool(b.cmd) } return nil } func buildInstances(cmd *Command, binst []*build.Instance, ignoreErrors bool) ([]*instance, error) { // TODO: // If there are no files and User is true, then use those? // Always use all files in user mode? instances, err := cmd.ctx.BuildInstances(binst) if err != nil { return nil, err } insts := make([]*instance, len(instances)) for i, v := range instances { insts[i] = &instance{ id: binst[i].ID(), err: binst[i].Err, val: v, } } // TODO: remove ignoreErrors flag and always return here, leaving it up to // clients to check for errors down the road. if ignoreErrors || flagIgnore.Bool(cmd) { return insts, nil } for _, inst := range instances { // TODO: consider merging errors of multiple files, but ensure // duplicates are removed. err := inst.Validate() if err != nil { if flagIgnore.Bool(cmd) { printError(cmd, err) } else { return nil, err } } } return insts, nil } func buildToolInstances(ctx *cue.Context, binst []*build.Instance) ([]*cue.Instance, error) { // Reuse the same context, if there is one, so that the @embed interpreter can be used. // Note that ctx may be nil when we do `cue help cmd`. r := new(cue.Runtime) if ctx != nil { r = (*cue.Runtime)(ctx) } instances, _ := r.BuildInstances(binst) for _, inst := range instances { if inst.Err != nil { return nil, inst.Err } } // TODO check errors after the fact in case of ignore. for _, inst := range instances { if err := inst.Value().Validate(); err != nil { return nil, err } } return instances, nil } func buildTools(cmd *Command, args []string) (*cue.Instance, error) { cfg, err := defaultConfig() if err != nil { return nil, err } loadCfg := *cfg.loadCfg loadCfg.Tools = true setTags(&loadCfg, cmd.cmdCmd.Flags()) binst := loadFromArgs(args, &loadCfg) if len(binst) == 0 { return nil, nil } included := map[string]bool{} ti := binst[0].Context().NewInstance(binst[0].Root, nil) // For @embed to also work in _tool.cue files, we must pass the module info along. ti.Module = binst[0].Module ti.Root = binst[0].Root for _, inst := range binst { k := 0 for _, f := range inst.Files { if strings.HasSuffix(f.Filename, "_tool.cue") { if !included[f.Filename] { _ = ti.AddSyntax(f) included[f.Filename] = true } continue } inst.Files[k] = f k++ } inst.Files = inst.Files[:k] } insts, err := buildToolInstances(cmd.ctx, binst) if err != nil { return nil, err } inst := insts[0] if len(insts) > 1 { inst = cue.Merge(insts...) } ctx := inst.Value().Context() for _, b := range binst { for _, i := range b.Imports { val := ctx.BuildInstance(i) if err := val.Err(); err != nil { return nil, err } } } // Set path equal to the package from which it is loading. ti.ImportPath = binst[0].ImportPath inst = inst.Build(ti) return inst, inst.Err } func shortFile(root string, f *build.File) string { dir, _ := filepath.Rel(root, f.Filename) if dir == "" { return f.Filename } if !filepath.IsAbs(dir) { dir = "." + string(filepath.Separator) + dir } return dir } cue-lang-cue-db9cc73/cmd/cue/cmd/completion.go000066400000000000000000000040021474664451600212560ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "github.com/spf13/cobra" ) var validCompletionArgs = []string{"bash", "zsh", "fish", "powershell"} const completionExample = ` Bash: $ source <(cue completion bash) # To load completions for each session, execute once: Linux: $ cue completion bash > /etc/bash_completion.d/cue MacOS: $ cue completion bash > /usr/local/etc/bash_completion.d/cue Zsh: $ source <(cue completion zsh) # To load completions for each session, execute once: $ cue completion zsh > "${fpath[1]}/_cue" Fish: $ cue completion fish | source # To load completions for each session, execute once: $ cue completion fish > ~/.config/fish/completions/cue.fish ` func newCompletionCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: fmt.Sprintf("completion %s", validCompletionArgs), Short: "Generate completion script", Long: ``, Example: completionExample, ValidArgs: validCompletionArgs, Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), RunE: mkRunE(c, runCompletion), } return cmd } func runCompletion(cmd *Command, args []string) error { w := cmd.OutOrStdout() switch args[0] { case "bash": cmd.Root().GenBashCompletion(w) case "zsh": cmd.Root().GenZshCompletion(w) case "fish": cmd.Root().GenFishCompletion(w, true) case "powershell": cmd.Root().GenPowerShellCompletion(w) default: return fmt.Errorf("%s is not a supported shell", args[0]) } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/custom.go000066400000000000000000000173021474664451600204260ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd // This file contains code or initializing and running custom commands. import ( "encoding/json" "io" "net/http" "net/http/httptest" "strings" "sync" "github.com/spf13/cobra" "cuelang.org/go/cue" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/core/adt" itask "cuelang.org/go/internal/task" "cuelang.org/go/internal/value" _ "cuelang.org/go/pkg/tool/cli" // Register tasks _ "cuelang.org/go/pkg/tool/exec" _ "cuelang.org/go/pkg/tool/file" _ "cuelang.org/go/pkg/tool/http" _ "cuelang.org/go/pkg/tool/os" "cuelang.org/go/tools/flow" ) const commandSection = "command" func lookupString(obj cue.Value, key, def string) string { str, err := obj.LookupPath(cue.MakePath(cue.Str(key))).String() if err == nil { def = str } return strings.TrimSpace(def) } // splitLine splits the first line and the rest of the string. func splitLine(s string) (line, tail string) { line = s if p := strings.IndexByte(s, '\n'); p >= 0 { line, tail = strings.TrimSpace(s[:p]), strings.TrimSpace(s[p+1:]) } return } // addCustomCommands iterates over all commands defined under field typ // and adds them as cobra subcommands to cmd. // The func is only used in `cue help cmd`, which doesn't show errors. func addCustomCommands(c *Command, cmd *cobra.Command, typ string, tools *cue.Instance) { commands := tools.Lookup(typ) if !commands.Exists() { return } fields, err := commands.Fields() if err != nil { return } for fields.Next() { sub, err := customCommand(c, commandSection, fields.Selector().Unquoted(), tools) if err == nil { cmd.AddCommand(sub) } } } // customCommand creates a cobra.Command out of a CUE command definition. func customCommand(c *Command, typ, name string, tools *cue.Instance) (*cobra.Command, error) { if tools == nil { return nil, errors.New("no commands defined") } // TODO: validate allowing incomplete. cmds := tools.Lookup(typ) o := cmds.Lookup(name) if !o.Exists() { return nil, o.Err() } // Ensure there is at least one tool file. // TODO: remove this block to allow commands to be defined in any file. _, w := value.ToInternal(cmds) hasToolFile := false w.VisitLeafConjuncts(func(c adt.Conjunct) bool { src := c.Source() if src == nil { return true } if strings.HasSuffix(src.Pos().Filename(), "_tool.cue") { hasToolFile = true return false } return true }) if !hasToolFile { // Note that earlier versions of this code checked cmds.Err in this scenario, // but it isn't clear why that was done, and we had no tests covering it. return nil, errors.Newf(token.NoPos, "could not find command %q", name) } docs := o.Doc() var usage, short, long string if len(docs) > 0 { txt := docs[0].Text() short, txt = splitLine(txt) short = lookupString(o, "short", short) if strings.HasPrefix(txt, "Usage:") { usage, txt = splitLine(txt[len("Usage:"):]) } usage = lookupString(o, "usage", usage) usage = lookupString(o, "$usage", usage) long = lookupString(o, "long", txt) } if !strings.HasPrefix(usage, name+" ") { usage = name } sub := &cobra.Command{ Use: usage, Short: lookupString(o, "$short", short), Long: lookupString(o, "$long", long), // Note that we don't use mkRunE here, as the parent func is already wrapped by // another mkRunE call, and all Command initialization has already happened. RunE: func(cmd *cobra.Command, args []string) error { // TODO: // - parse flags and env vars // - constrain current config with config section return doTasks(c, name, tools) }, } // TODO: implement var/flag handling. return sub, nil } func doTasks(cmd *Command, command string, root *cue.Instance) error { cfg := &flow.Config{ Root: cue.MakePath(cue.Str(commandSection), cue.Str(command)), InferTasks: true, IgnoreConcrete: true, } c := flow.New(cfg, root, newTaskFunc(cmd)) return c.Run(backgroundContext()) } // func (r *customRunner) tagReference(t *task, ref cue.Value) error { // inst, path := ref.Reference() // if len(path) == 0 { // return errors.Newf(ref.Pos(), // "$after must be a reference or list of references, found %s", ref) // } // if inst != r.root { // return errors.Newf(ref.Pos(), // "reference in $after must refer to value in same package") // } // // TODO: allow referring to group of tasks. // if !r.tagDependencies(t, path) { // return errors.Newf(ref.Pos(), // "reference %s does not refer to task or task group", // strings.Join(path, "."), // TODO: more correct representation. // ) // } // return nil // } func isTask(v cue.Value) bool { // This mimics the v0.2 behavior. The cutoff is really quite arbitrary. A // sane implementation should not use InferTasks, really. if len(v.Path().Selectors()) == 0 { return false } if v.Kind() != cue.StructKind { return false } if v.Lookup("$id").Exists() { return true } // Is it an existing legacy kind. str, err := v.Lookup("kind").String() _, ok := legacyKinds[str] return err == nil && ok } var legacyKinds = map[string]string{ "exec": "tool/exec.Run", "http": "tool/http.Do", "print": "tool/cli.Print", "testserver": "cmd/cue/cmd.Test", } func newTaskFunc(cmd *Command) flow.TaskFunc { return func(v cue.Value) (flow.Runner, error) { if !isTask(v) { return nil, nil } kind, err := v.Lookup("$id").String() if err != nil { // Lookup kind for backwards compatibility. // This should not be supported for cue run. var err1 error kind, err1 = v.Lookup("kind").String() if err1 != nil || legacyKinds[kind] == "" { return nil, errors.Promote(err1, "newTask") } } var isLegacy bool if k, ok := legacyKinds[kind]; ok { kind = k isLegacy = true } rf := itask.Lookup(kind) if rf == nil { return nil, errors.Newf(v.Pos(), "runner of kind %q not found", kind) } // Verify entry against template. v = value.UnifyBuiltin(v, kind) if err := v.Err(); err != nil { err = v.Validate() return nil, errors.Promote(err, "newTask") } runner, err := rf(v) if err != nil { return nil, errors.Promote(err, "errors running task") } return flow.RunnerFunc(func(t *flow.Task) error { obj := t.Value() if isLegacy { obj = obj.Unify(v) } c := &itask.Context{ Context: t.Context(), Stdin: cmd.InOrStdin(), Stdout: cmd.OutOrStdout(), Stderr: cmd.OutOrStderr(), Obj: obj, } value, err := runner.Run(c) if err != nil { return err } if value != nil { _ = t.Fill(value) } return nil }), nil } } func init() { itask.Register("cmd/cue/cmd.Test", newTestServerCmd) } var testServerOnce = sync.OnceValue(func() string { s := httptest.NewServer(http.HandlerFunc( func(w http.ResponseWriter, req *http.Request) { data, _ := io.ReadAll(req.Body) d := map[string]string{ "data": string(data), "when": "now", } enc := json.NewEncoder(w) _ = enc.Encode(d) })) return s.URL }) func newTestServerCmd(v cue.Value) (itask.Runner, error) { return testServerCmd(testServerOnce()), nil } type testServerCmd string func (s testServerCmd) Run(ctx *itask.Context) (x interface{}, err error) { return map[string]interface{}{"url": string(s)}, nil } cue-lang-cue-db9cc73/cmd/cue/cmd/def.go000066400000000000000000000041201474664451600176440ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "github.com/spf13/cobra" "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" ) // newDefCmd creates a new eval command func newDefCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "def", Short: "print consolidated definitions", Long: `def prints consolidated configuration as a single file. Printing is skipped if validation fails. The --expression flag is used to only print parts of a configuration. `, RunE: mkRunE(c, runDef), } addOutFlags(cmd.Flags(), true) addOrphanFlags(cmd.Flags()) addInjectionFlags(cmd.Flags(), false, false) cmd.Flags().StringArrayP(string(flagExpression), "e", nil, "evaluate this expression only") cmd.Flags().BoolP(string(flagAttributes), "A", false, "display field attributes") cmd.Flags().Bool(string(flagInlineImports), false, "expand references to non-core imports") // TODO: Option to include comments in output. return cmd } func runDef(cmd *Command, args []string) error { b, err := parseArgs(cmd, args, &config{mode: filetypes.Def}) if err != nil { return err } e, err := encoding.NewEncoder(cmd.ctx, b.outFile, b.encConfig) if err != nil { return err } iter := b.instances() defer iter.close() for iter.scan() { var err error if f := iter.file(); f != nil { err = e.EncodeFile(f) } else { err = e.Encode(iter.value()) } if err != nil { return err } } if err := iter.err(); err != nil { return err } if err := e.Close(); err != nil { return err } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/eval.go000066400000000000000000000104201474664451600200350ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "github.com/spf13/cobra" "cuelang.org/go/cue" "cuelang.org/go/cue/build" "cuelang.org/go/cue/format" "cuelang.org/go/internal" "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" ) // newEvalCmd creates a new eval command func newEvalCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "eval", Short: "evaluate and print a configuration", Long: `eval evaluates, validates, and prints a configuration. Printing is skipped if validation fails. The --expression flag is used to evaluate an expression within the configuration file, instead of the entire configuration file itself. Examples: $ cat < foo.cue a: ["a", "b", "c"] EOF $ cue eval foo.cue -e a[0] -e a[2] "a" "c" `, RunE: mkRunE(c, runEval), } addOutFlags(cmd.Flags(), true) addOrphanFlags(cmd.Flags()) addInjectionFlags(cmd.Flags(), false, false) cmd.Flags().StringArrayP(string(flagExpression), "e", nil, "evaluate this expression only") cmd.Flags().BoolP(string(flagConcrete), "c", false, "require the evaluation to be concrete") cmd.Flags().BoolP(string(flagHidden), "H", false, "display hidden fields") cmd.Flags().BoolP(string(flagOptional), "O", false, "display optional fields") cmd.Flags().BoolP(string(flagAttributes), "A", false, "display field attributes") cmd.Flags().BoolP(string(flagAll), "a", false, "show optional and hidden fields") // TODO: Option to include comments in output. return cmd } const ( flagConcrete flagName = "concrete" flagHidden flagName = "show-hidden" flagOptional flagName = "show-optional" flagAttributes flagName = "show-attributes" ) func runEval(cmd *Command, args []string) error { b, err := parseArgs(cmd, args, &config{mode: filetypes.Eval}) if err != nil { return err } syn := []cue.Option{ cue.Final(), // for backwards compatibility cue.Definitions(true), cue.Attributes(flagAttributes.Bool(cmd)), cue.Optional(flagAll.Bool(cmd) || flagOptional.Bool(cmd)), cue.ErrorsAsValues(flagIgnore.Bool(cmd)), } // Keep for legacy reasons. Note that `cue eval` is to be deprecated by // `cue` eventually. opts := []format.Option{ format.UseSpaces(4), format.TabIndent(false), } if flagSimplify.Bool(cmd) { opts = append(opts, format.Simplify()) } b.encConfig.Format = opts e, err := encoding.NewEncoder(cmd.ctx, b.outFile, b.encConfig) if err != nil { return err } iter := b.instances() defer iter.close() for i := 0; iter.scan(); i++ { id := "" if len(b.insts) > 1 { id = iter.id() } v := iter.value() errHeader := func() { if id != "" { fmt.Fprintf(cmd.OutOrStderr(), "// %s\n", id) } } if b.outFile.Encoding != build.CUE { err := e.Encode(v) if err != nil { errHeader() printError(cmd, err) } continue } if flagConcrete.Bool(cmd) { syn = append(syn, cue.Concrete(true)) } if flagHidden.Bool(cmd) || flagAll.Bool(cmd) { syn = append(syn, cue.Hidden(true)) } if len(b.expressions) > 1 { b, _ := format.Node(b.expressions[i%len(b.expressions)]) id = string(b) } if !flagIgnore.Bool(cmd) { if err := v.Err(); err != nil { errHeader() return v.Validate(syn...) } // TODO(#553): this can be removed once v.Syntax() below retains line // information. if e.IsConcrete() || flagConcrete.Bool(cmd) { if err := v.Validate(cue.Concrete(true)); err != nil { errHeader() printError(cmd, err) continue } } } f := internal.ToFile(v.Syntax(syn...)) f.Filename = id err := e.EncodeFile(f) if err != nil { errHeader() printError(cmd, err) } } if err := iter.err(); err != nil { return err } if err := e.Close(); err != nil { return err } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/exp.go000066400000000000000000000063031474664451600177070ustar00rootroot00000000000000// Copyright 2024 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "cuelang.org/go/cue/load" "cuelang.org/go/internal/encoding/gotypes" "github.com/spf13/cobra" ) func newExpCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ // Experimental commands are hidden by design. Hidden: true, Use: "exp [arguments]", Short: "experimental commands", Long: ` exp groups commands which are still in an experimental stage. Experimental commands may be changed or removed at any time, as the objective is to gain experience and then move the feature elsewhere. `[1:], RunE: mkRunE(c, func(cmd *Command, args []string) error { stderr := cmd.Stderr() if len(args) == 0 { fmt.Fprintln(stderr, "exp must be run as one of its subcommands") } else { fmt.Fprintf(stderr, "exp must be run as one of its subcommands: unknown subcommand %q\n", args[0]) } fmt.Fprintln(stderr, "Run 'cue help exp' for known subcommands.") return ErrPrintedError }), } cmd.AddCommand(newExpGenGoTypesCmd(c)) return cmd } func newExpGenGoTypesCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "gengotypes", Short: "generate Go types from CUE definitions", Long: ` gengotypes generates Go type definitions from exported CUE definitions. The generated Go types are guaranteed to accept any value accepted by the CUE definitions, but may be more general. For example, "string | int" will translate into the Go type "any" because the Go type system is not able to express disjunctions. To ensure that the resulting Go code works, any imported CUE packages or referenced CUE definitions are transitively generated as well. The generated code is placed in cue_gen.go files in the directory of each CUE package. Generated Go type and field names may differ from the original CUE names by default. For instance, an exported definition "#foo" becomes "Foo", given that Go uses capitalization to export names in a package, and a nested definition like "#foo.#bar" becomes "Foo_Bar", given that Go does not allow declaring nested types. @go attributes can be used to override which name or type to be generated, for example: package foo @go(betterpkgname) renamed: int @go(BetterName) retyped: string @go(,type=foo.com/bar.NamedString) The attribute "@go(-)" can be used to ignore a definition or field, for example: #ignoredDefinition: { @go(-) } ignoredField: int @go(-) `[1:], // TODO: write a long help text once the feature set is reasonably stable. RunE: mkRunE(c, runExpGenGoTypes), } return cmd } func runExpGenGoTypes(cmd *Command, args []string) error { insts := load.Instances(args, &load.Config{}) return gotypes.Generate(cmd.ctx, insts...) } cue-lang-cue-db9cc73/cmd/cue/cmd/export.go000066400000000000000000000070421474664451600204350ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "github.com/spf13/cobra" "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" ) // newExportCmd creates and export command func newExportCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "export", Short: "output data in a standard format", Long: `export evaluates the configuration found in the current directory and prints the emit value to stdout. Examples: Evaluated and emit # a single file cue export config.cue # multiple files: these are combined at the top-level. Order doesn't matter. cue export file1.cue foo/file2.cue # all files within the "cloud" package, including all files in the # current directory and its ancestor directories that are marked with the # same package, up to the root of the containing module. cue export .:cloud # the package name can be omitted if the directory only contains files for # the "cloud" package. cue export Emit value: For CUE files, the generated configuration is derived from the top-level single expression, the emit value. For example, the file // config.cue arg1: 1 arg2: "my string" { a: arg1 b: arg2 } yields the following JSON: { "arg1": 1, "a": 1, "arg2": "my string", "b": "my string" } In absence of arguments, the current directory is loaded as a package instance. A package instance for a directory contains all files in the directory and its ancestor directories, up to the module root, belonging to the same package. If a single package is not uniquely defined by the files in the current directory then the package name must be specified as an explicit argument using ".:" syntax. Formats The following formats are recognized: cue output as CUE Outputs any CUE value. json output as JSON Outputs any CUE value. yaml output as YAML Outputs any CUE value. text output as raw text The evaluated value must be of type string. binary output as raw binary The evaluated value must be of type string or bytes. `, // TODO: some formats are missing for sure, like "jsonl" or "textproto" from internal/filetypes/types.cue. RunE: mkRunE(c, runExport), } addOutFlags(cmd.Flags(), true) addOrphanFlags(cmd.Flags()) addInjectionFlags(cmd.Flags(), false, false) cmd.Flags().Bool(string(flagEscape), false, "use HTML escaping") cmd.Flags().StringArrayP(string(flagExpression), "e", nil, "export this expression only") return cmd } func runExport(cmd *Command, args []string) error { b, err := parseArgs(cmd, args, &config{mode: filetypes.Export}) if err != nil { return err } enc, err := encoding.NewEncoder(cmd.ctx, b.outFile, b.encConfig) if err != nil { return err } iter := b.instances() defer iter.close() for iter.scan() { v := iter.value() err := enc.Encode(v) if err != nil { return err } } if err := iter.err(); err != nil { return err } if err := enc.Close(); err != nil { return err } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/fix.go000066400000000000000000000062031474664451600177000ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "io/fs" "os" "path/filepath" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/cue/load" "cuelang.org/go/cue/token" "cuelang.org/go/tools/fix" "github.com/spf13/cobra" ) func newFixCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "fix [packages]", Short: "rewrite packages to latest standards", Long: `Fix finds CUE programs that use old syntax and old APIs and rewrites them to use newer ones. After you update to a new CUE release, fix helps make the necessary changes to your program. Without any packages, fix applies to all files within a module. `, RunE: mkRunE(c, runFixAll), } cmd.Flags().BoolP(string(flagForce), "f", false, "rewrite even when there are errors") return cmd } func runFixAll(cmd *Command, args []string) error { var opts []fix.Option if flagSimplify.Bool(cmd) { opts = append(opts, fix.Simplify()) } if len(args) == 0 { args = []string{"./..."} dir := rootWorkingDir for { if _, err := os.Stat(filepath.Join(dir, "cue.mod")); err == nil { args = appendDirs(args, filepath.Join(dir, "cue.mod", "gen")) args = appendDirs(args, filepath.Join(dir, "cue.mod", "pkg")) args = appendDirs(args, filepath.Join(dir, "cue.mod", "usr")) break } dir = filepath.Dir(dir) if info, _ := os.Stat(dir); !info.IsDir() { return errors.Newf(token.NoPos, "no module root found") } } } instances := load.Instances(args, &load.Config{ Tests: true, Tools: true, Package: "*", }) errs := fix.Instances(instances, opts...) if errs != nil && flagForce.Bool(cmd) { return errs } done := map[*ast.File]bool{} for _, i := range instances { for _, f := range i.Files { if done[f] || (f.Filename != "-" && !strings.HasSuffix(f.Filename, ".cue")) { continue } done[f] = true b, err := format.Node(f) if err != nil { errs = errors.Append(errs, errors.Promote(err, "format")) } if f.Filename == "-" { if _, err := cmd.OutOrStdout().Write(b); err != nil { return err } } else { if err := os.WriteFile(f.Filename, b, 0666); err != nil { errs = errors.Append(errs, errors.Promote(err, "write")) } } } } return errs } func appendDirs(a []string, base string) []string { _ = filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error { if err == nil && entry.IsDir() && path != base { short := filepath.ToSlash(path[len(base)+1:]) if strings.ContainsAny(short, "/") { a = append(a, short) } } return nil }) return a } cue-lang-cue-db9cc73/cmd/cue/cmd/flags.go000066400000000000000000000133261474664451600202120ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "github.com/spf13/pflag" ) // Common flags const ( flagAll flagName = "all" flagAllErrors flagName = "all-errors" flagCheck flagName = "check" flagDiff flagName = "diff" flagDryRun flagName = "dry-run" flagEscape flagName = "escape" flagExpression flagName = "expression" flagExt flagName = "ext" flagFiles flagName = "files" flagForce flagName = "force" flagGlob flagName = "name" flagIgnore flagName = "ignore" flagInject flagName = "inject" flagInjectVars flagName = "inject-vars" flagInlineImports flagName = "inline-imports" flagJSON flagName = "json" flagLanguageVersion flagName = "language-version" flagList flagName = "list" flagMerge flagName = "merge" flagOut flagName = "out" flagOutFile flagName = "outfile" flagPackage flagName = "package" flagPath flagName = "path" flagProtoEnum flagName = "proto_enum" flagProtoPath flagName = "proto_path" flagRecursive flagName = "recursive" flagSchema flagName = "schema" flagSimplify flagName = "simplify" flagSource flagName = "source" flagStrict flagName = "strict" flagTrace flagName = "trace" flagVerbose flagName = "verbose" flagWithContext flagName = "with-context" // Hidden flags. flagCpuProfile flagName = "cpuprofile" flagMemProfile flagName = "memprofile" ) func addOutFlags(f *pflag.FlagSet, allowNonCUE bool) { if allowNonCUE { f.String(string(flagOut), "", `output format (run 'cue help filetypes' for more info)`) } f.StringP(string(flagOutFile), "o", "", `filename or - for stdout with optional file prefix (run 'cue help filetypes' for more info)`) f.BoolP(string(flagForce), "f", false, "force overwriting existing files") } func addGlobalFlags(f *pflag.FlagSet) { f.Bool(string(flagTrace), false, "trace computation") f.BoolP(string(flagSimplify), "s", false, "simplify output") f.BoolP(string(flagIgnore), "i", false, "proceed in the presence of errors") f.BoolP(string(flagVerbose), "v", false, "print information about progress") f.BoolP(string(flagAllErrors), "E", false, "print all available errors") // Deprecated flags are hidden but still work for now. // TODO(mvdan): make this flag give a warning or error in early 2025. f.Bool(string(flagStrict), false, "report errors for lossy mappings (deprecated: use \"jsonschema+strict:\" filetype instead; see cue help filetypes)") f.MarkHidden(string(flagStrict)) f.String(string(flagCpuProfile), "", "write a CPU profile to the specified file before exiting") f.MarkHidden(string(flagCpuProfile)) f.String(string(flagMemProfile), "", "write an allocation profile to the specified file before exiting") f.MarkHidden(string(flagMemProfile)) } func addOrphanFlags(f *pflag.FlagSet) { f.StringP(string(flagPackage), "p", "", "package name for non-CUE files") f.StringP(string(flagSchema), "d", "", "expression to select schema for evaluating values in non-CUE files") f.StringArrayP(string(flagPath), "l", nil, "CUE expression for single path component (see 'cue help flags' for details)") f.Bool(string(flagList), false, "concatenate multiple objects into a list") f.Bool(string(flagWithContext), false, "import as object with contextual data") f.StringArrayP(string(flagProtoPath), "I", nil, "paths in which to search for imports") f.String(string(flagProtoEnum), "int", "mode for rendering enums (int|json)") f.StringP(string(flagGlob), "n", "", "glob filter for non-CUE file names in directories") f.Bool(string(flagMerge), true, "merge non-CUE files") } func addInjectionFlags(f *pflag.FlagSet, auto, hidden bool) { f.StringArrayP(string(flagInject), "t", nil, "set the value of a tagged field") f.BoolP(string(flagInjectVars), "T", auto, "inject system variables in tags") if hidden { f.Lookup(string(flagInject)).Hidden = true f.Lookup(string(flagInjectVars)).Hidden = true } } type flagName string // ensureAdded detects if a flag is being used without it first being // added to the flagSet. Because flagNames are global, it is quite // easy to accidentally use a flag in a command without adding it to // the flagSet. func (f flagName) ensureAdded(cmd *Command) { if cmd.Flags().Lookup(string(f)) == nil { panic(fmt.Sprintf("Cmd %q uses flag %q without adding it", cmd.Name(), f)) } } // IsSet reports whether f was provided by the user, which is useful to tell // `cue` apart from `cue --flag=` when the flag's default value is the zero value. func (f flagName) IsSet(cmd *Command) bool { f.ensureAdded(cmd) found := false cmd.Flags().Visit(func(pf *pflag.Flag) { if pf.Name == string(f) { found = true } }) return found } func (f flagName) Bool(cmd *Command) bool { f.ensureAdded(cmd) v, _ := cmd.Flags().GetBool(string(f)) return v } func (f flagName) String(cmd *Command) string { f.ensureAdded(cmd) v, _ := cmd.Flags().GetString(string(f)) return v } func (f flagName) StringArray(cmd *Command) []string { f.ensureAdded(cmd) v, _ := cmd.Flags().GetStringArray(string(f)) return v } cue-lang-cue-db9cc73/cmd/cue/cmd/fmt.go000066400000000000000000000135711474664451600177060ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "fmt" "io" "io/fs" "os" "path/filepath" "slices" "strings" "github.com/rogpeppe/go-internal/diff" "github.com/spf13/cobra" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/cue/load" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/internal/filetypes" "cuelang.org/go/internal/source" ) func newFmtCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "fmt [-s] [inputs]", Short: "formats CUE configuration files", Long: `Fmt formats the given files or the files for the given packages in place Arguments are interpreted as import paths (see 'cue help inputs') unless --files is set, in which case the arguments are file paths to descend into and format all CUE files. Directories named "cue.mod" and those beginning with "." and "_" are skipped unless given as explicit arguments. `, RunE: mkRunE(c, func(cmd *Command, args []string) error { check := flagCheck.Bool(cmd) doDiff := flagDiff.Bool(cmd) formatOpts := []format.Option{} if flagSimplify.Bool(cmd) { formatOpts = append(formatOpts, format.Simplify()) } var foundBadlyFormatted bool if !flagFiles.Bool(cmd) { // format packages builds := loadFromArgs(args, &load.Config{ Tests: true, Tools: true, AllCUEFiles: true, Package: "*", SkipImports: true, }) if len(builds) == 0 { return errors.Newf(token.NoPos, "invalid args") } for _, inst := range builds { if err := inst.Err; err != nil { return err } for _, file := range inst.BuildFiles { shouldFormat := inst.User || file.Filename == "-" || filepath.Dir(file.Filename) == inst.Dir if !shouldFormat { continue } wasModified, err := formatFile(file, formatOpts, doDiff, check, cmd) if err != nil { return err } if wasModified { foundBadlyFormatted = true } } } } else { // format individual files hasDots := slices.ContainsFunc(args, func(arg string) bool { return strings.Contains(arg, "...") }) if hasDots { return errors.New(`cannot use "..." in --files mode`) } if len(args) == 0 { args = []string{"."} } processFile := func(path string) error { file, err := filetypes.ParseFile(path, filetypes.Input) if err != nil { return err } if path == "-" { contents, err := io.ReadAll(cmd.InOrStdin()) if err != nil { return err } file.Source = contents } wasModified, err := formatFile(file, formatOpts, doDiff, check, cmd) if err != nil { return err } if wasModified { foundBadlyFormatted = true } return nil } for _, arg := range args { if arg == "-" { if err := processFile(arg); err != nil { return err } continue } arg = filepath.Clean(arg) if err := filepath.WalkDir(arg, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { name := d.Name() isMod := name == "cue.mod" isDot := strings.HasPrefix(name, ".") && name != "." && name != ".." if path != arg && (isMod || isDot || strings.HasPrefix(name, "_")) { return filepath.SkipDir } return nil } if !strings.HasSuffix(path, ".cue") { return nil } return processFile(path) }); err != nil { return err } } } if check && foundBadlyFormatted { return ErrPrintedError } return nil }), } cmd.Flags().Bool(string(flagCheck), false, "exits with non-zero status if any files are not formatted") cmd.Flags().BoolP(string(flagDiff), "d", false, "display diffs instead of rewriting files") cmd.Flags().Bool(string(flagFiles), false, "treat arguments as file paths to descend into rather than import paths") return cmd } // formatFile formats a single file. // It returns true if the file was not well formatted. func formatFile(file *build.File, opts []format.Option, doDiff, check bool, cmd *Command) (bool, error) { // We buffer the input and output bytes to compare them. // This allows us to determine whether a file is already // formatted, without modifying the file. src, err := source.ReadAll(file.Filename, file.Source) if err != nil { return false, err } syntax, err := parser.ParseFile(file.Filename, src, parser.ParseComments) if err != nil { return false, err } formatted, err := format.Node(syntax, opts...) if err != nil { return false, err } stdout := cmd.OutOrStdout() // Always write to stdout if the file is read from stdin. if file.Filename == "-" && !doDiff && !check { stdout.Write(formatted) } // File is already well formatted; we can stop here. if bytes.Equal(formatted, src) { return false, nil } path, err := filepath.Rel(rootWorkingDir, file.Filename) if err != nil { path = file.Filename } switch { case doDiff: d := diff.Diff(path+".orig", src, path, formatted) fmt.Fprintln(stdout, string(d)) case check: fmt.Fprintln(stdout, path) case file.Filename == "-": // already wrote the formatted source to stdout above default: if err := os.WriteFile(file.Filename, formatted, 0666); err != nil { return false, err } } return true, nil } cue-lang-cue-db9cc73/cmd/cue/cmd/get.go000066400000000000000000000033331474664451600176720ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "github.com/spf13/cobra" ) func newGetCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "get [packages]", Short: "add non-CUE dependencies to the current module", Long: `Get downloads packages or modules for non-CUE languages to include them in the module's pkg directory. Get requires an additional language field to determine for which language definitions should be fetched. Definitions are extracted from the source of the respective language and stored. The specifics on how dependencies are fetched and converted vary per language and are documented in the respective subcommands. For information on native CUE modules: cue help modules `, RunE: mkRunE(c, func(cmd *Command, args []string) error { stderr := cmd.Stderr() if len(args) == 0 { fmt.Fprintln(stderr, "get must be run as one of its subcommands") } else { fmt.Fprintf(stderr, "get must be run as one of its subcommands: unknown subcommand %q\n", args[0]) } fmt.Fprintln(stderr, "Run 'cue help get' for known subcommands.") return ErrPrintedError }), } cmd.AddCommand(newGoCmd(c)) return cmd } cue-lang-cue-db9cc73/cmd/cue/cmd/get_go.go000066400000000000000000001133131474664451600203570ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "fmt" "go/ast" "go/token" "go/types" "os" "path" "path/filepath" "reflect" "regexp" "slices" "strconv" "strings" "unicode" "github.com/spf13/cobra" "golang.org/x/tools/go/packages" cueast "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/format" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/load" "cuelang.org/go/cue/parser" cuetoken "cuelang.org/go/cue/token" "cuelang.org/go/internal" ) // TODO: // Document: // - Use ast package. // - how to deal with "oneOf" or sum types? // - generate cue files for cue field tags? // - cue go get or cue get go // - include generation report in doc_gen.cue or report.txt. // Possible enums: // package foo // Type: enumType func newGoCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "go [packages]", Short: "add Go dependencies to the current module", Long: `go converts Go types into CUE definitions The command "cue get go" is like "go get", but converts the retrieved Go packages to CUE. The retrieved packages are put in the CUE module's pkg directory at the import path of the corresponding Go package. The converted definitions are available to any CUE file within the CUE module by using this import path. The Go type definitions are converted to CUE based on how they would be interpreted by Go's encoding/json package. Definitions for a Go file foo.go are written to a CUE file named foo_go_gen.cue. It is safe for users to add additional files to the generated directories, as long as their name does not end with _gen.*. Rules of Converting Go types to CUE Go structs are converted to cue structs adhering to the following conventions: - field names are translated based on the definition of a "json" or "yaml" tag, in that order. - embedded structs marked with a json inline tag unify with struct definition. For instance, the Go struct struct MyStruct { Common ` + "json:\",inline\"" + ` Field string } translates to the CUE struct #MyStruct: Common & { Field: string } - a type that implements MarshalJSON, UnmarshalJSON, MarshalYAML, or UnmarshalYAML is translated to top (_) to indicate it may be any value. For some Go core types for which the implementation of these methods is known, like time.Time, the type may be more specific. - a type implementing MarshalText or UnmarshalText is represented as the CUE type string - slices and arrays convert to CUE lists, except when the element type is byte, in which case it translates to the CUE bytes type. In the case of arrays, the length of the CUE value is constrained accordingly, when possible. - Maps translate to a CUE struct, where all elements are constrained to be of Go map element type. Like for JSON, maps may only have string keys. - Pointers translate to a sum type with the default value of null and the Go type as an alternative value. - Field tags are translated to CUE's field attributes. In some cases, the contents are rewritten to reflect the corresponding types in CUE. The @go attribute is added if the field name or type definition differs between the generated CUE and the original Go. Native CUE Constraints Native CUE constraints may be defined in separate cue files alongside the generated files either in the original Go directory or in the generated directory. These files can impose additional constraints on types and values that are not otherwise expressible in Go. The package name for these CUE files must be the same as that of the Go package. For instance, for the type package foo type IP4String string defined in the Go package, one could add a cue file foo.cue with the following contents to allow IP4String to assume only valid IP4 addresses: package foo // IP4String defines a valid IP4 address. #IP4String: =~#"^\#(byte)\.\#(byte)\.\#(byte)\.\#(byte)$"# // byte defines string allowing integer values of 0-255. byte = #"([01]?\d?\d|2[0-4]\d|25[0-5])"# The "cue get go" command copies any cue files in the original Go package directory that has a package clause with the same name as the Go package to the destination directory, replacing its .cue ending with _gen.cue. Alternatively, the additional native constraints can be added to the generated package, as long as the file name does not end with _gen.cue. Running cue get go again to regenerate the package will never overwrite any files not ending with _gen.*. Constants and Enums Go does not have an enum or sum type. Conventionally, a type that is supposed to be an enum is followed by a const block with the allowed values for that type. However, as that is only a guideline and not a hard rule, these cases cannot be translated to CUE disjunctions automatically. Constant values, however, are generated in a way that makes it easy to convert a type to a proper enum using native CUE constraints. For instance, the Go type package foo type Switch int const ( Off Switch = iota On ) translates into the following CUE definitions: package foo #Switch: int // #enumSwitch #enumSwitch: Off | On Off: 0 On: 1 This definition allows any integer value for #Switch, while the #enumSwitch value defines all defined constants for Switch and thus all valid values if #Switch were to be interpreted as an enum type. To turn #Switch into an enum, include the following constraint in, say, enum.cue, in either the original source directory or the generated directory: package foo // limit the valid values for Switch to those existing as constants with // the same type. #Switch: #enumSwitch This tells CUE that only the values enumerated by #enumSwitch are valid values for #Switch. Note that there are now two definitions of #Switch. CUE handles this in the usual way by unifying the two definitions, in which case the more restrictive enum interpretation of #Switch remains. `, // - TODO: interpret cuego's struct tags and annotations. RunE: mkRunE(c, extract), } cmd.Flags().StringP(string(flagExclude), "e", "", "comma-separated list of regexps of identifiers to omit") cmd.Flags().Bool(string(flagLocal), false, "generates files in the main module locally") cmd.Flags().StringP(string(flagPackage), "p", "", "package name for generated CUE files") return cmd } const ( flagExclude flagName = "exclude" flagLocal flagName = "local" ) func (e *extractor) initExclusions(str string) { e.exclude = str for _, re := range strings.Split(str, ",") { if re != "" { e.exclusions = append(e.exclusions, regexp.MustCompile(re)) } } } func (e *extractor) filter(name string) bool { for _, ex := range e.exclusions { if ex.MatchString(name) { return true } } return false } type extractor struct { cmd *Command allPkgs map[string]*packages.Package done map[string]bool // per package orig map[types.Type]*ast.StructType usedPkgs map[string]bool // per file cmap ast.CommentMap pkg *packages.Package consts map[string][]string pkgNames map[string]pkgInfo exclusions []*regexp.Regexp exclude string } type pkgInfo struct { id string name string } func (e *extractor) logf(format string, args ...interface{}) { if flagVerbose.Bool(e.cmd) { fmt.Fprintf(e.cmd.Stderr(), format+"\n", args...) } } func (e *extractor) usedPkg(pkg string) { e.usedPkgs[pkg] = true } var ( typeAny = types.Universe.Lookup("any").Type() // any or interface{} typeByte = types.Universe.Lookup("byte").Type() // byte typeBytes = types.NewSlice(typeByte) // []byte typeString = types.Universe.Lookup("string").Type() // string typeError = types.Universe.Lookup("error").Type() // error ) // Note that we can leave positions, packages, and parameter/result names empty. // They are not used by go/types.Implements. func typeMethod(name string, params, results []types.Type) *types.Func { return types.NewFunc(token.NoPos, nil, name, typeSignature(params, results)) } func typeSignature(params, results []types.Type) *types.Signature { paramVars := make([]*types.Var, len(params)) for i, param := range params { paramVars[i] = types.NewParam(token.NoPos, nil, "", param) } resultVars := make([]*types.Var, len(results)) for i, result := range results { resultVars[i] = types.NewParam(token.NoPos, nil, "", result) } return types.NewSignatureType( nil, nil, nil, types.NewTuple(paramVars...), types.NewTuple(resultVars...), false, ) } // Note that we record these interfaces without names, so they will show up in // the logs like "interface{MarshalJSON() ([]uint8, error)}" rather than // encoding/json.Marshaler. We could construct named types if need be. var toTop = []*types.Interface{ // json.Marshaler: interface { MarshalJSON() ([]byte, error) } types.NewInterfaceType([]*types.Func{ typeMethod("MarshalJSON", nil, []types.Type{typeBytes, typeError}), }, nil).Complete(), // json.Unmarshaler: interface { UnmarshalJSON([]byte) error } types.NewInterfaceType([]*types.Func{ typeMethod("UnmarshalJSON", []types.Type{typeBytes}, []types.Type{typeError}), }, nil).Complete(), // yaml.Marshaler: interface { MarshalYAML() (interface{}, error) } types.NewInterfaceType([]*types.Func{ typeMethod("MarshalYAML", nil, []types.Type{typeAny, typeError}), }, nil).Complete(), // yaml.Unmarshaler: interface { UnmarshalYAML(func(interface{}) error) error } types.NewInterfaceType([]*types.Func{ typeMethod("UnmarshalYAML", []types.Type{ typeSignature([]types.Type{typeAny}, []types.Type{typeError}), }, []types.Type{typeError}), }, nil).Complete(), } var toString = []*types.Interface{ // encoding.TextMarshaler: interface { MarshalText() ([]byte, error) } types.NewInterfaceType([]*types.Func{ typeMethod("MarshalText", nil, []types.Type{typeBytes, typeError}), }, nil).Complete(), // encoding.TextUnmarshaler: interface { UnmarshalText([]byte) error } types.NewInterfaceType([]*types.Func{ typeMethod("UnmarshalText", []types.Type{typeBytes}, []types.Type{typeError}), }, nil).Complete(), } // TODO: // - consider not including types with any dropped fields. func extract(cmd *Command, args []string) error { // TODO the CUE load using "." (below) assumes that a CUE module and a Go // module will exist within the same directory (more precisely a Go module // could be nested within a CUE module), such that the module path in any // subdirectory below the current directory will be the same. This seems an // entirely reasonable restriction, but also one that we should enforce. // // Enforcing this restriction also makes --local entirely redundant. // command specifies a Go package(s) that belong to the main module // and where for some reason the // determine module root: binst := loadFromArgs([]string{"."}, nil)[0] // TODO: require explicitly set root. root := binst.Root cfg := &packages.Config{ Mode: packages.NeedName | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedModule, } pkgs, err := packages.Load(cfg, args...) if err != nil { return err } var errs []string for _, p := range pkgs { for _, e := range p.Errors { switch e.Kind { case packages.ParseError, packages.TypeError: // TODO: Consider making this behavior an option. default: errs = append(errs, fmt.Sprintf("\t%s: %v", p.PkgPath, e)) } } } if len(errs) > 0 { return fmt.Errorf("could not load Go packages:\n%s", strings.Join(errs, "\n")) } e := extractor{ cmd: cmd, allPkgs: map[string]*packages.Package{}, orig: map[types.Type]*ast.StructType{}, } e.initExclusions(flagExclude.String(cmd)) e.done = map[string]bool{} for _, p := range pkgs { e.done[p.PkgPath] = true e.addPackage(p) } for _, p := range pkgs { if err := e.extractPkg(root, p); err != nil { return err } } return nil } func (e *extractor) addPackage(p *packages.Package) { if pkg, ok := e.allPkgs[p.PkgPath]; ok { if p != pkg { panic(fmt.Sprintf("duplicate package %s", p.PkgPath)) } return } e.allPkgs[p.PkgPath] = p for _, pkg := range p.Imports { e.addPackage(pkg) } } func (e *extractor) recordTypeInfo(p *packages.Package) { for _, f := range p.Syntax { ast.Inspect(f, func(n ast.Node) bool { switch n := n.(type) { case *ast.StructType: e.orig[p.TypesInfo.TypeOf(n)] = n } return true }) } } func (e *extractor) extractPkg(root string, p *packages.Package) error { e.pkg = p e.logf("--- Package %s", p.PkgPath) e.recordTypeInfo(p) e.consts = map[string][]string{} for _, f := range p.Syntax { for _, d := range f.Decls { switch d := d.(type) { case *ast.GenDecl: e.recordConsts(d) } } } pkg := p.PkgPath dir := filepath.Join(load.GenPath(root), filepath.FromSlash(pkg)) isMain := flagLocal.Bool(e.cmd) && p.Module != nil && p.Module.Main if isMain { dir = p.Module.Dir sub := p.PkgPath[len(p.Module.Path):] if sub != "" { dir = filepath.FromSlash(dir + sub) } } if err := os.MkdirAll(dir, 0777); err != nil { return err } e.usedPkgs = map[string]bool{} args := pkg if e.exclude != "" { args += " --exclude=" + e.exclude } for i, f := range p.Syntax { e.cmap = ast.NewCommentMap(p.Fset, f, f.Comments) e.pkgNames = map[string]pkgInfo{} for _, spec := range f.Imports { pkgPath, _ := strconv.Unquote(spec.Path.Value) pkg := p.Imports[pkgPath] info := pkgInfo{id: pkgPath, name: pkg.Name} if path.Base(pkgPath) != pkg.Name { info.id += ":" + pkg.Name } if spec.Name != nil { info.name = spec.Name.Name } e.pkgNames[pkgPath] = info } decls := []cueast.Decl{} for _, d := range f.Decls { switch d := d.(type) { case *ast.GenDecl: decls = append(decls, e.reportDecl(d)...) } } if len(decls) == 0 && f.Doc == nil { continue } pName := flagPackage.String(e.cmd) if pName == "" { pName = p.Name } pkg := &cueast.Package{Name: e.ident(pName, false)} addDoc(f.Doc, pkg) f := &cueast.File{Decls: []cueast.Decl{ &cueast.CommentGroup{List: []*cueast.Comment{ {Text: "// Code generated by cue get go. DO NOT EDIT."}, }}, &cueast.CommentGroup{List: []*cueast.Comment{ {Text: "//cue:generate cue get go " + args}, }}, pkg, }} f.Decls = append(f.Decls, decls...) if err := astutil.Sanitize(f); err != nil { return err } file := filepath.Base(p.CompiledGoFiles[i]) file = strings.Replace(file, ".go", "_go", 1) file += "_gen.cue" b, err := format.Node(f, format.Simplify()) if err != nil { return err } err = os.WriteFile(filepath.Join(dir, file), b, 0666) if err != nil { return err } } if !isMain { if err := e.importCUEFiles(p, dir, args); err != nil { return err } } for path := range e.usedPkgs { if !e.done[path] { e.done[path] = true if err := e.extractPkg(root, e.allPkgs[path]); err != nil { return err } } } return nil } func (e *extractor) importCUEFiles(p *packages.Package, dstDir, args string) error { // A package's Go files will often share directories, // for example all original source files will sit in the same directory. // Deduplicate the directories so we don't repeat work. var srcDirs []string for _, path := range p.CompiledGoFiles { srcDirs = append(srcDirs, filepath.Dir(path)) } slices.Sort(srcDirs) srcDirs = slices.Compact(srcDirs) for _, srcDir := range srcDirs { entries, err := os.ReadDir(srcDir) if err != nil { return err } for _, entry := range entries { if entry.IsDir() { continue } name := entry.Name() path := filepath.Join(srcDir, name) name, ok := strings.CutSuffix(name, ".cue") if !ok { continue } f, err := parser.ParseFile(path, nil, parser.PackageClauseOnly) if err != nil { return err } if pkg := f.PackageName(); pkg != "" && pkg == p.Name { w := &bytes.Buffer{} fmt.Fprintf(w, "// Code generated by cue get go. DO NOT EDIT.\n\n") fmt.Fprintf(w, "//cue:generate cue get go %v\n\n", args) b, err := os.ReadFile(path) if err != nil { return err } w.Write(b) dst := filepath.Join(dstDir, name+"_gen.cue") if err := os.WriteFile(dst, w.Bytes(), 0666); err != nil { return err } } } } return nil } func (e *extractor) recordConsts(x *ast.GenDecl) { if x.Tok != token.CONST { return } for _, s := range x.Specs { v, ok := s.(*ast.ValueSpec) if !ok { continue } for _, n := range v.Names { typ := e.pkg.TypesInfo.TypeOf(n).String() e.consts[typ] = append(e.consts[typ], n.Name) } } } func (e *extractor) strLabel(name string) cueast.Label { return cueast.NewString(name) } func (e *extractor) ident(name string, isDef bool) *cueast.Ident { if isDef { r := []rune(name)[0] name = "#" + name if !unicode.Is(unicode.Lu, r) { name = "_" + name } } return cueast.NewIdent(name) } func (e *extractor) def(doc *ast.CommentGroup, name string, value cueast.Expr, newline bool) *cueast.Field { f := &cueast.Field{ Label: e.ident(name, true), // Go identifiers are always valid CUE identifiers. Value: value, } addDoc(doc, f) if newline { cueast.SetRelPos(f, cuetoken.NewSection) } return f } func (e *extractor) reportDecl(x *ast.GenDecl) (a []cueast.Decl) { switch x.Tok { case token.TYPE: for _, s := range x.Specs { v, ok := s.(*ast.TypeSpec) if !ok || e.filter(v.Name.Name) { continue } typ := e.pkg.TypesInfo.TypeOf(v.Name) enums := e.consts[typ.String()] name := v.Name.Name mapNamed := false underlying := e.pkg.TypesInfo.TypeOf(v.Type) if b, ok := underlying.Underlying().(*types.Basic); ok && b.Kind() != types.String { switch b.Kind() { case types.Invalid: continue case types.String: default: mapNamed = true } } switch tn, ok := e.pkg.TypesInfo.Defs[v.Name].(*types.TypeName); { case ok: if altType := e.altType(tn.Type()); altType != nil { // TODO: add the underlying tag as a Go tag once we have // proper string escaping for CUE. a = append(a, e.def(x.Doc, name, altType, true)) break } fallthrough default: if !supportedType(nil, typ) { e.logf(" Dropped declaration %v of unsupported type %v", name, typ) continue } if s := e.altType(typ); s != nil { a = append(a, e.def(x.Doc, name, s, true)) break } f, _ := e.makeField(name, definition, underlying, x.Doc, true) a = append(a, f) cueast.SetRelPos(f, cuetoken.NewSection) } if len(enums) > 0 && ast.IsExported(name) { enumName := "#enum" + name cueast.AddComment(a[len(a)-1], internal.NewComment(false, enumName)) // Constants are mapped as definitions. var exprs []cueast.Expr var named []cueast.Decl for _, v := range enums { if v == "_" { continue } label := cueast.NewString(v) cueast.SetRelPos(label, cuetoken.Blank) var x cueast.Expr = e.ident(v, true) cueast.SetRelPos(x, cuetoken.Newline) exprs = append(exprs, x) if !mapNamed { continue } named = append(named, &cueast.Field{ Label: label, Value: e.ident(v, true), }) } addField := func(label string, exprs []cueast.Expr) { f := &cueast.Field{ Label: cueast.NewIdent(label), Value: cueast.NewBinExpr(cuetoken.OR, exprs...), } cueast.SetRelPos(f, cuetoken.NewSection) a = append(a, f) } addField(enumName, exprs) if len(named) > 0 { f := &cueast.Field{ Label: cueast.NewIdent("#values_" + name), Value: &cueast.StructLit{Elts: named}, } cueast.SetRelPos(f, cuetoken.NewSection) a = append(a, f) } } } case token.CONST: // TODO: copy over comments for constant blocks. for k, s := range x.Specs { // TODO: determine type name and filter. v, ok := s.(*ast.ValueSpec) if !ok { continue } for i, name := range v.Names { if name.Name == "_" || e.filter(name.Name) { continue } f := e.def(v.Doc, name.Name, nil, k == 0) a = append(a, f) val := "" if i < len(v.Values) { if lit, ok := v.Values[i].(*ast.BasicLit); ok { val = lit.Value } } typ := e.pkg.TypesInfo.TypeOf(name) c := e.pkg.TypesInfo.Defs[v.Names[i]].(*types.Const) sv := c.Val().ExactString() cv, err := parser.ParseExpr("", sv) if err != nil { panic(fmt.Errorf("failed to parse %v: %v", sv, err)) } // Use the original Go value if compatible with CUE (octal is okay) if b, ok := cv.(*cueast.BasicLit); ok { if b.Kind == cuetoken.INT && val != "" && val[0] != '\'' { b.Value = val } if b.Value != val { cueast.AddComment(cv, internal.NewComment(false, val)) } } switch typ { case typeByte, typeString, typeError: default: if basic, ok := typ.(*types.Basic); ok && basic.Info()&types.IsUntyped != 0 { break // untyped basic types do not make valid identifiers } cv = cueast.NewBinExpr(cuetoken.AND, e.makeType(typ), cv) } f.Value = cv } } } return a } func shortTypeName(t types.Type) string { if n, ok := t.(*types.Named); ok { return n.Obj().String() // fully qualified, e.g. "foo/bar.Baz" } return t.String() // anonymous, e.g. "interface{Method() []byte}" } func (e *extractor) altType(typ types.Type) cueast.Expr { // We need to check whether T or *T implement each interface I. // Typically we would just need to check whether *T implements I, // as the method set of *T includes the method set of T, // but that doesn't work when T is an interface type. // See https://go.dev/ref/spec#Method_sets. // // TODO(mvdan): perhaps check with T when it's an interface, // and with *T otherwise, avoiding double calls to types.Implements. ptr := types.NewPointer(typ) for _, iface := range toTop { if types.Implements(typ, iface) || types.Implements(ptr, iface) { t := shortTypeName(typ) e.logf(" %v implements %s; setting type to _", t, iface) return e.ident("_", false) } } for _, iface := range toString { if types.Implements(typ, iface) || types.Implements(ptr, iface) { t := shortTypeName(typ) e.logf(" %v implements %s; setting type to string", t, iface) return e.ident("string", false) } } return nil } func addDoc(g *ast.CommentGroup, x cueast.Node) bool { doc := makeDoc(g, true) if doc != nil { cueast.AddComment(x, doc) return true } return false } func makeDoc(g *ast.CommentGroup, isDoc bool) *cueast.CommentGroup { if g == nil { return nil } a := []*cueast.Comment{} for _, comment := range g.List { c := comment.Text // Remove comment markers. // The parser has given us exactly the comment text. switch c[1] { case '/': //-style comment (no newline at the end) a = append(a, &cueast.Comment{Text: c}) case '*': /*-style comment */ c = c[2 : len(c)-2] if len(c) > 0 && c[0] == '\n' { c = c[1:] } lines := strings.Split(c, "\n") // Find common space prefix i := 0 line := lines[0] for ; i < len(line); i++ { if c := line[i]; c != ' ' && c != '\t' { break } } for _, l := range lines { for j := 0; j < i && j < len(l); j++ { if line[j] != l[j] { i = j break } } } // Strip last line if empty. if n := len(lines); n > 1 && len(lines[n-1]) < i { lines = lines[:n-1] } // Print lines. for _, l := range lines { if i >= len(l) { a = append(a, &cueast.Comment{Text: "//"}) continue } a = append(a, &cueast.Comment{Text: "// " + l[i:]}) } } } return &cueast.CommentGroup{Doc: isDoc, List: a} } func supportedType(stack []types.Type, t types.Type) (ok bool) { // handle recursive types for _, t0 := range stack { if t0 == t { return true } } stack = append(stack, t) if named, ok := t.(*types.Named); ok { obj := named.Obj() // Redirect or drop Go standard library types. if obj.Pkg() == nil { // error interface return true } switch obj.Pkg().Path() { case "time": switch named.Obj().Name() { case "Time", "Duration", "Location", "Month", "Weekday": return true } return false case "math/big": switch named.Obj().Name() { case "Int", "Float": return true } // case "net": // // TODO: IP, Host, SRV, etc. // case "url": // // TODO: URL and Values } } // Note that underlying types are never aliases. t = t.Underlying() switch t := t.(type) { case *types.Basic: return t.Kind() != types.Invalid case *types.Named: return true case *types.Pointer: return supportedType(stack, t.Elem()) case *types.Slice: return supportedType(stack, t.Elem()) case *types.Array: return supportedType(stack, t.Elem()) case *types.Map: if b, ok := t.Key().Underlying().(*types.Basic); !ok || b.Kind() != types.String { return false } return supportedType(stack, t.Elem()) case *types.Struct: // Eliminate structs with fields for which all fields are filtered. if t.NumFields() == 0 { return true } for i := 0; i < t.NumFields(); i++ { f := t.Field(i) if f.Exported() && supportedType(stack, f.Type()) { return true } } case *types.Interface: return true } return false } type fieldKind int const ( regular fieldKind = iota optional definition ) func (e *extractor) makeField(name string, kind fieldKind, expr types.Type, doc *ast.CommentGroup, newline bool) (f *cueast.Field, typename string) { typ := e.makeType(expr) var label cueast.Label if kind == definition { label = e.ident(name, true) } else { label = e.strLabel(name) } f = &cueast.Field{Label: label, Value: typ} if doc := makeDoc(doc, newline); doc != nil { f.AddComment(doc) cueast.SetRelPos(doc, cuetoken.NewSection) } var tok cuetoken.Token switch kind { case definition: // neither optional nor required. case regular: // TODO(required): use idiomatic CUE (token.NOT) if CUE version is // higher than a certain number? We may not be able to determine this // accurately enough. case optional: tok = cuetoken.OPTION } internal.SetConstraint(f, tok) b, _ := format.Node(typ) return f, string(b) } func (e *extractor) makeType(typ types.Type) (result cueast.Expr) { switch typ := types.Unalias(typ).(type) { case *types.Named: obj := typ.Obj() if obj.Pkg() == nil { return e.ident("_", false) } // Check for builtin packages. switch { case obj.Pkg().Path() == "time" && obj.Name() == "Time": ref := e.ident(e.pkgNames[obj.Pkg().Path()].name, false) var name *cueast.Ident if ref.Name != "time" { name = e.ident(ref.Name, false) } ref.Node = cueast.NewImport(name, "time") return cueast.NewSel(ref, obj.Name()) case obj.Pkg().Path() == "time" && obj.Name() == "Duration": // Go's time.Duration is an int64 to represent nanoseconds, // and even though most Go users would find the string representation // like "3s" or "40m" most reasonable and readable for constant values, // encoding/json is bound via Go's compatibility promise to encoding as integers. // // Since compatibility with JSON encoding and decoding in Go // is more important than readability, we use integers as well here. // Note that this means we aren't compatible with CUE's own time.Duration, // which is rather unfortunate, but we have to choose one or the other. // // TODO(mvdan): reconsider once 'cue get go' is more configurable, // and especially once encoding/json/v2 becomes a reality, // as it does encode time.Duration via strings rather than integers. // For example, could we generate types like 'int | *time.Duration' // and constants like '300 | *"300ns"' to support both at the same time? return e.ident("int", false) case obj.Pkg().Path() == "math/big" && obj.Name() == "Int": return e.ident("int", false) default: if !strings.ContainsAny(obj.Pkg().Path(), ".") { // Drop any standard library type if they haven't been handled // above. // TODO: Doc? if s := e.altType(obj.Type()); s != nil { return s } } } result = e.ident(obj.Name(), true) if pkg := obj.Pkg(); pkg != nil && pkg != e.pkg.Types { info := e.pkgNames[pkg.Path()] if info.name == "" { info.name = pkg.Name() } p := e.ident(info.name, false) var name *cueast.Ident if info.name != pkg.Name() { name = e.ident(info.name, false) } if info.id == "" { // This may happen if an alias is defined in a different file // within this package referring to yet another package. info.id = pkg.Path() } p.Node = cueast.NewImport(name, info.id) // makeType is always called to describe a type, so whatever // this is referring to, it must be a definition. result = cueast.NewSel(p, "#"+obj.Name()) e.usedPkg(pkg.Path()) } // TODO(uhthomas): Fields with type parameters should not be // top. // // For example: // // type A[T any] struct { // SomeField T // } // // type B A[string] // // Should become: // // #A: SomeField: _ // // #B: #A & { // _#T: string // SomeField: _#T // } // // Or maybe: // // #A: { // #T: _ // SomeField: #T // } // // #B: #A & { // #T: string // } // // The values of x.TypeParams() and x.TypeArgs() may be helpful. // params := x.TypeParams() // args := x.TypeArgs() // if params.Len() > 0 { // var fields []any // for i := 0; i < params.Len(); i++ { // name := params.At(i).Obj().Name() // fields = append(fields, e.ident(name, true), e.makeType(args.At(i))) // } // return cueast.NewBinExpr(cuetoken.AND, result, cueast.NewStruct(fields...)) // } return result case *types.Pointer: return &cueast.BinaryExpr{ X: cueast.NewNull(), Op: cuetoken.OR, Y: e.makeType(typ.Elem()), } case *types.Struct: st := &cueast.StructLit{ Lbrace: cuetoken.Blank.Pos(), Rbrace: cuetoken.Newline.Pos(), } e.addFields(typ, st) return st case *types.Slice: // Note that []byte is treated different from []uint8, // even though byte is an alias for the basic type uint8. // TODO: reconsider this; both encoding/json and the future v2 // encode []uint8, or anything assignable to []byte, as bytes. if typ.Elem() == typeByte { return e.ident("bytes", false) } return cueast.NewList(&cueast.Ellipsis{Type: e.makeType(typ.Elem())}) case *types.Array: if typ.Elem() == typeByte { // TODO: no way to constrain lengths of bytes for now, as regexps // operate on Unicode, not bytes. So we need // fmt.Fprint(e.w, fmt.Sprintf("=~ '^\C{%d}$'", x.Len())), // but regexp does not support that. // But translate to bytes, instead of [...byte] to be consistent. return e.ident("bytes", false) } else { return &cueast.BinaryExpr{ X: &cueast.BasicLit{ Kind: cuetoken.INT, Value: strconv.Itoa(int(typ.Len())), }, Op: cuetoken.MUL, Y: cueast.NewList(e.makeType(typ.Elem())), } } case *types.Map: if b, ok := typ.Key().Underlying().(*types.Basic); !ok || b.Kind() != types.String { panic(fmt.Sprintf("unsupported map key type %T", typ.Key())) } f := &cueast.Field{ Label: cueast.NewList(e.ident("string", false)), Value: e.makeType(typ.Elem()), } cueast.SetRelPos(f, cuetoken.Blank) return &cueast.StructLit{ Lbrace: cuetoken.Blank.Pos(), Elts: []cueast.Decl{f}, Rbrace: cuetoken.Blank.Pos(), } case *types.Basic: switch typ.Kind() { case types.Uintptr, types.UnsafePointer: return e.ident("uint64", false) case types.Byte: return e.ident("uint8", false) case types.Complex64, types.Complex128: return e.ident("_", false) } return e.ident(typ.Name(), false) case *types.Union: var exprs []cueast.Expr for i := 0; i < typ.Len(); i++ { exprs = append(exprs, e.makeType(typ.Term(i).Type())) } return cueast.NewBinExpr(cuetoken.OR, exprs...) case *types.Interface: // TODO(uhthomas): Should interfaces with methods (IsMethodSet) // be set to top? if !typ.IsComparable() { return e.ident("_", false) } // TODO(uhthomas): Simplify expressions. // // For example: // // int | (int | string) // // Should really become: // // int | string // var exprs []cueast.Expr for i := 0; i < typ.NumEmbeddeds(); i++ { exprs = append(exprs, e.makeType(typ.EmbeddedType(i))) } return cueast.NewBinExpr(cuetoken.OR, exprs...) case *types.TypeParam: return e.makeType(typ.Constraint()) default: // record error panic(fmt.Sprintf("unsupported type %T", typ)) } } func (e *extractor) addAttr(f *cueast.Field, tag, body string) { s := fmt.Sprintf("@%s(%s)", tag, body) f.Attrs = append(f.Attrs, &cueast.Attribute{Text: s}) } func (e *extractor) addFields(x *types.Struct, st *cueast.StructLit) { add := func(x cueast.Decl) { st.Elts = append(st.Elts, x) } s := e.orig[x] docs := []*ast.CommentGroup{} for _, f := range s.Fields.List { if len(f.Names) == 0 { docs = append(docs, f.Doc) } else { for range f.Names { docs = append(docs, f.Doc) } } } count := 0 for i := 0; i < x.NumFields(); i++ { f := x.Field(i) if !ast.IsExported(f.Name()) { continue } if !supportedType(nil, f.Type()) { e.logf(" Dropped field %v for unsupported type %v", f.Name(), f.Type()) continue } if f.Anonymous() && e.isInline(x.Tag(i)) { typ := f.Type() for { p, ok := typ.(*types.Pointer) if !ok { break } typ = p.Elem() } switch typ := types.Unalias(typ).(type) { case *types.Named: embed := &cueast.EmbedDecl{Expr: e.makeType(typ)} if i > 0 { cueast.SetRelPos(embed, cuetoken.NewSection) } add(embed) case *types.Struct: e.addFields(typ, st) default: panic(fmt.Sprintf("unimplemented embedding for type %T", x)) } continue } tag := x.Tag(i) name := getName(f.Name(), tag) if name == "-" { continue } doc := docs[i] // TODO: check referrers kind := regular if e.isOptional(f, doc, tag) { kind = optional } field, cueType := e.makeField(name, kind, f.Type(), doc, count > 0) add(field) if s := reflect.StructTag(tag).Get("cue"); s != "" { expr, err := parser.ParseExpr("get go", s) if err != nil { e.logf("error parsing struct tag %q:", s, err) } field.Value = cueast.NewBinExpr(cuetoken.AND, field.Value, expr) } // Add field tag to convert back to Go. typeName := f.Type().String() // simplify type names: for path, info := range e.pkgNames { typeName = strings.ReplaceAll(typeName, path+".", info.name+".") } typeName = strings.ReplaceAll(typeName, e.pkg.Types.Path()+".", "") cueStr := strings.ReplaceAll(cueType, "_#", "") cueStr = strings.ReplaceAll(cueStr, "#", "") // TODO: remove fields in @go attr that are the same as printed? if name != f.Name() || typeName != cueStr { buf := &strings.Builder{} if name != f.Name() { buf.WriteString(f.Name()) } if typeName != cueStr { if strings.ContainsAny(typeName, `#"',()=`) { typeName = literal.String.Quote(typeName) } fmt.Fprint(buf, ",", typeName) } e.addAttr(field, "go", buf.String()) } // Carry over protobuf field tags with modifications. // TODO: consider trashing the protobuf tag, as the Go versions are // lossy and will not allow for an accurate translation in some cases. tags := reflect.StructTag(tag) if t := tags.Get("protobuf"); t != "" { split := strings.Split(t, ",") k := 0 for _, s := range split { if strings.HasPrefix(s, "name=") && s[len("name="):] == name { continue } split[k] = s k++ } split = split[:k] // Put tag first, as type could potentially be elided and is // "more optional". if len(split) >= 2 { split[0], split[1] = split[1], split[0] } // Interpret as map? if len(split) > 2 && split[1] == "bytes" { tk := tags.Get("protobuf_key") tv := tags.Get("protobuf_val") if tk != "" && tv != "" { tk, _, _ = strings.Cut(tk, ",") tv, _, _ = strings.Cut(tv, ",") split[1] = fmt.Sprintf("map[%s]%s", tk, tv) } } e.addAttr(field, "protobuf", strings.Join(split, ",")) } // Carry over XML tags. if t := reflect.StructTag(tag).Get("xml"); t != "" { e.addAttr(field, "xml", t) } // Carry over TOML tags. if t := reflect.StructTag(tag).Get("toml"); t != "" { e.addAttr(field, "toml", t) } // TODO: should we in general carry over any unknown tag verbatim? count++ } } func (e *extractor) isInline(tag string) bool { return hasFlag(tag, "json", "inline", 1) || hasFlag(tag, "yaml", "inline", 1) } func (e *extractor) isOptional(f *types.Var, doc *ast.CommentGroup, tag string) bool { if _, ok := f.Type().(*types.Pointer); ok { return true } for _, line := range strings.Split(doc.Text(), "\n") { before, _, _ := strings.Cut(strings.TrimSpace(line), "=") if before == "+optional" { return true } } // TODO: also when the type is a list or other kind of pointer. return hasFlag(tag, "json", "omitempty", 1) || hasFlag(tag, "yaml", "omitempty", 1) } func hasFlag(tag, key, flag string, offset int) bool { if t := reflect.StructTag(tag).Get(key); t != "" { split := strings.Split(t, ",") if offset >= len(split) { return false } for _, str := range split[offset:] { if str == flag { return true } } } return false } func getName(name string, tag string) string { tags := reflect.StructTag(tag) for _, s := range []string{"json", "yaml"} { if tag, ok := tags.Lookup(s); ok { if p := strings.Index(tag, ","); p >= 0 { tag = tag[:p] } if tag != "" { return tag } } } // TODO: should we also consider to protobuf name? Probably not. return name } cue-lang-cue-db9cc73/cmd/cue/cmd/help.go000066400000000000000000000744561474664451600200610ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bufio" "fmt" "strings" "github.com/spf13/cobra" "cuelang.org/go/internal/mod/modresolve" "cuelang.org/go/mod/modconfig" ) // TODO: intersperse the examples at the end of the texts in the // body of text to make things more concrete for the user early on? // The current approach works will if users just print the text without // "more" or "less", in which case the examples show more prominently. // The user can then scroll up to get a more in-depth explanation. But is // this how users use it? // newHelpCmd is similar to the built-in help command from cobra, // but knows how to load custom commands in `cue help cmd`. func newHelpCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "help [command]", Short: "show help text for a command or topic", Hidden: true, // not shown as a runnable command in `cue help` Run: func(_ *cobra.Command, args []string) { findCmd := func() (*cobra.Command, bool) { cmd, rest, err := c.Root().Find(args) found := cmd != nil && err == nil && len(rest) == 0 return cmd, found } cmd, found := findCmd() // Treat `cue help help` as an unknown help topic; just use `cue help`. if found && cmd.Name() == "help" { cmd, found = nil, false } isCmd := len(args) > 0 && args[0] == "cmd" if isCmd { // args is one of: // // ["cmd"] // ["cmd", "mycmd"] // ["cmd", "mycmd", "./mypkg"] // // In the third case, we want to load ["./mypkg"] // and we want to look up the help for ["cmd", "mycmd"]. var pkgArgs []string if len(args) > 2 { pkgArgs = args[2:] args = args[:2] } tools, err := buildTools(c, pkgArgs) if err == nil { addCustomCommands(c, cmd, commandSection, tools) // For the sake of `cue help cmd mycmd`, find the command again. cmd, found = findCmd() } } if !found { if isCmd { // Note that for args ["cmd", "mycmd", "./mypkg"] we only want "mycmd". fmt.Fprintf(c.Stderr(), "Unknown cmd command: %s\n", args[1]) } else { fmt.Fprintf(c.Stderr(), "Unknown help topic: %s\n", strings.Join(args, " ")) } if cmd == nil { cobra.CheckErr(c.Root().Usage()) } else { cobra.CheckErr(cmd.Usage()) } } else { cobra.CheckErr(cmd.Help()) } }, } return cmd } // We use a custom Cobra help text template for the sake of being a bit more // in control of its formatting, as well as the contents of the root `cue help`. var helpTemplate = ` {{- if not .HasParent}}{{/* Special template for the root help. */ -}} CUE makes it easy to validate data, write schemas, and ensure configurations align with policies. CUE works with a wide range of tools and formats that you're already using such as Go, JSON, YAML, OpenAPI, and JSON Schema. For more information and documentation, see: https://cuelang.org Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}} Use "{{.CommandPath}} help [command]" for more information about a command. {{/* We want to show additional help topics from the root command's help text even though they are only reachable via 'cue help'. */ -}} Additional help topics:{{range .Commands}}{{if eq .Name "help"}}{{range .Commands}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}} {{else}}{{/* Subcommands use a fairly standard template. */ -}} {{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}} {{- end -}} ` var helpTopics = []*cobra.Command{ commandsHelp, embedHelp, environmentHelp, filetypeHelp, flagsHelp, injectHelp, inputsHelp, modulesHelp, registryConfigHelp, } var inputsHelp = &cobra.Command{ Use: "inputs", Short: "package list, patterns, and files", Long: `Many commands apply to a set of inputs: cue [inputs] The list [inputs] may specify CUE packages, CUE files, non-CUE files or some combinations of those. An empty list specifies the package in the current directory, provided there is a single named package in this directory. CUE packages are specified as an import path. An import path that begins with a "." or ".." element is a relative import path, is interpreted as a file system path, and denotes the package instance in that directory. Otherwise, the import path P is absolute and denotes a package that may be external, usually found in an external registry. It may also refer to a package in cue.mod/{pkg|gen|usr}/P - this is legacy behavior that might be removed at a later date. An absolute import path is of the form P or P@vN where vN is the major version of the module containing the package. An import path is mapped to a registry location by consulting cue.mod/module.cue and the registry configuration (see "cue help modules" and "cue help registryconfig" for more details). An import may contain a ":name" suffix to indicate a specific package to load within a given path. It is necessary to specify this when there is more than one package at the path. For example, the following import path specifies a package named "other" in some external module with major version v1. foo.example/bar/baz@v1:other A local import path may contain one or more "..." to match any subdirectory: pkg/... matches all packages below pkg, including pkg itself, while foo/.../bar matches all directories named bar within foo. In all cases, directories containing cue.mod directories are excluded from the result. "..." is not currently supported in external import paths. Directory and file names that begin with "." or "_" are ignored, unless explicitly listed as inputs. File with names ending "_tool.cue" are ignored unless running "cue cmd" and they are in packages explicitly mentioned on the command line. Files with names ending "_test.cue" are ignored for the time being; they are reserved for future testing functionality. A package may also be specified as a list of .cue files. The special symbol '-' denotes stdin or stdout and defaults to the cue file type for stdin. For stdout, the default depends on the cue command. A .cue file package may not be combined with regular packages. Non-cue files are interpreted based on their file extension or, if present, an explicit file qualifier (see the "filetypes" help topic). By default, all recognized files are unified at their root value. See the "filetypes" and "flags" help topics on how to treat each file individually or how to combine them differently. If a data file has multiple values, such as allowed with JSON Lines or YAML, each value is interpreted as a separate file. If the --schema/-d is specified, data files are not merged, and are compared against the specified schema within a package or non-data file. For OpenAPI, the -d flag specifies a schema name. For JSON Schema the -d flag specifies a schema defined in "definitions". In all other cases, the -d flag is a CUE expression that is evaluated within the package. Examples (also see also "flags" and "filetypes" help topics): # Show the definition of each package named foo for each # directory dir under path. $ cue def ./path/.../dir:foo # Unify each document in foo.yaml with the value Foo in pkg. $ cue export ./pkg -d Foo foo.yaml # Unify data.json with schema.json. $ cue export data.json schema: schema.json `, } var embedHelp = &cobra.Command{ Use: "embed", Short: "file embedding", Long: ` The @embed attribute can be used to load files as part of CUE evaluation. Embedding must be enabled by a file-level @extern(embed) attribute. Embed a single file as follows, which must exist when evaluating: @extern(embed) package foo a: _ @embed(file=foo.json) Embed many files of the same type with a glob pattern, which inserts one field per file matched: b: _ @embed(glob=images/*.*, type=binary) b: [string]: bytes Note that "**" glob patterns are not supported at this time. If the file extension in "file" or "glob" does not imply a file type, it must be specified with the "type" encoding as shown above. See the "filetypes" help topic for more. Files containing multiple documents cannot be embedded directly. For NDJSON or multi-document YAML files, embed as type=text and use APIs like yaml.Extract to decode as a list. Note that embedding cue files is not supported at this time. Note: support for embed is experimental, and can be disabled via CUE_EXPERIMENT=embed=0. For more details and discussion, see the proposal linked from https://cuelang.org/discussion/3264. `[1:], } var environmentHelp = &cobra.Command{ Use: "environment", Short: "environment variables", Long: ` The cue command consults environment variables for configuration. If an environment variable is unset or empty, sensible default setting is used. CUE_CACHE_DIR A directory structure to hold files which are reused between operations. It defaults to a directory for user-specific temporary data, such as: - "$XDG_CACHE_HOME/cue" or "$HOME/.cache/cue" on Linux - "$HOME/Library/Caches/cue" on MacOS - "%LocalAppData%/cue" on Windows Its contents are generally read-only and include: - mod/download for modules fetched from registries - mod/extract for extracted module archives CUE_CONFIG_DIR A directory to hold configuration and long-lived state files. It defaults to a directory for user-specific persistent data, such as: - "$XDG_CONFIG_HOME/cue" or "$HOME/.config/cue" on Linux - "$HOME/Library/Application Support/cue" on MacOS - "%AppData%/cue" on Windows CUE_REGISTRY The configuration to use when downloading and publishing modules. See "cue help registryconfig" for details. CUE_EXPERIMENT Comma-separated list of experiment flags to enable or disable: evalv3 Enable the new CUE evaluator, addressing performance issues and bringing a better disjunction algorithm. embed Enable support for embedded data files as described in https://cuelang.org/discussion/3264. decodeint64 (default true) Tweak cue.Value.Decode to choose "int64" rather than "int" as the default Go type for CUE integer values. toposort Enable topological sorting of struct fields. Provide feedback via https://cuelang.org/issue/3558 CUE_DEBUG Comma-separated list of debug flags to enable or disable, such as: http Log a JSON message per HTTP request and response made when interacting with module registries. sortfields Force fields in stucts to be sorted lexicographically. openinline (default true) Permit disallowed fields to be selected into literal struct that would normally result in a close error, mimicking evalv2 closedness behavior in evalv3 to aid the transition. CUE_EXPERIMENT and CUE_DEBUG are comma-separated lists of key-value strings, where the value is a boolean "true" or "1" if omitted. For example: CUE_EXPERIMENT=toenable,todisable=0 `[1:], } // Please keep the CUE_EXPERIMENT and CUE_DEBUG lists above in sync with // the cueexperiment and cuedebug packages. var modulesHelp = &cobra.Command{ Use: "modules", Short: "module support", Long: `Modules are how CUE publishes packages and manages dependencies. A module is a collection of packages that are released, versioned, and distributed together. Modules are downloaded from OCI-compliant artifact registries. The Central Registry for CUE modules (` + modconfig.DefaultRegistry + `) is used as the source for external modules by default. For a detailed reference on modules: https://cuelang.org/docs/reference/modules/ For information on commands that interact with modules: cue help mod For tutorials on how to use the Central Registry, see: https://cuelang.org/docs/tutorial/working-with-the-central-registry/ https://cuelang.org/docs/tutorial/publishing-modules-to-the-central-registry/ For a tutorial on how to work with a custom OCI registry for CUE modules: https://cuelang.org/docs/tutorial/working-with-a-custom-module-registry/ For information on how to specify the CUE registry: cue help registryconfig `, } var registryConfigHelp = &cobra.Command{ Use: "registryconfig", Short: "module registry configuration", Long: `The registry configuration determines how CUE maps modules to their locations in OCI registries. Given a particular registry configuration, it's possible to work what registry a given module is stored in, and what repository within that registry, without making any network calls. If no explicit registry configuration is present, a default Central Registry (` + modconfig.DefaultRegistry + `) is used for all modules. The simplest way of specifying a registry configuration is to set $CUE_REGISTRY to the hostname of that registry. Examples: CUE_REGISTRY=myregistry.example CUE_REGISTRY=localhost:5000 CUE_REGISTRY='[::1]:5000' The special name "none" can be used to indicate that no registry should be used. If a path is present too, all modules will be stored under that path. For example: CUE_REGISTRY=localhost:5000/all/modules/will/be/stored/here By default for hosts other than localhost, a secure (HTTPS) connection will be used. This default can be set by appending "+insecure" or "+secure". For example: CUE_REGISTRY=100.98.141.117:5000+insecure CUE_REGISTRY=localhost:5000/modules+secure When specified in this way, the registry is used to fetch all modules. To use a specific registry for only certain subsets of modules, a prefix can be specified. This constrains a registry to be used only for modules that match that prefix. If there are multiple registries with a prefix, the longest matching prefix wins. When matching a prefix, only complete path elements (non-slash characters) are considered. It's an error if there are two identical prefixes in the same registry configuration. For example: CUE_REGISTRY='foo.example/bar=localhost:5000,myregistry.example' In the above example, modules with the prefix "foo.example/bar", such as "foo.example/bar/somemodule" (but not "foo.example/barry"), will be fetched from the registry at localhost:5000. All other modules will be fetched from "myregistry.example". Note that the syntax above implies that the ordering of the elements in CUE_REGISTRY isn't important because the resolution algorithm is order-independent. To specify that no registry should be used for a given module prefix, the special name "none" can be used. For example: CUE_REGISTRY='foo.example/bar=none,myregistry.example' In the above example, any attempt to fetch a module under "foo.example/bar" will result in a failure. Note that this will not take effect if the module is already present in the on-disk cache, which is consulted before looking at CUE_REGISTRY. Customizing Name Resolution Some registries have restrictions on what repositories can be used. For example, a registry implementation might restrict the depth of the available repository paths, or might even provide access to a single repository only. In order to accommodate these kinds of limitation, a registry configuration can also be specified in CUE syntax, usually as a configuration file. To do this, set CUE_REGISTRY to "file:" followed by the path to the configuration file. For example: CUE_REGISTRY=file:/home/alice/.config/cue/registry.cue To remove ambiguity, the simpler syntax described earlier can be explicitly requested with the "simple:" prefix. For example: CUE_REGISTRY=simple:myregistry.example If it is preferable not to create a file on disk for the configuration, the "inline:" prefix can be used: CUE_REGISTRY='inline:defaultRegistry: registry: "myregistry.example"' The configuration file syntax is described by the following CUE #file schema definition: ` + indent(modresolve.RegistryConfigSchema()), } var flagsHelp = &cobra.Command{ Use: "flags", Short: "common flags for composing packages", Long: `Non-CUE files are merged at their roots by default. The can be combined differently or treated as different files by using a combination of the following flags. Individual files To treat non-cue files as individual files, use --no-merge flag. This is the default for vet. This flag only applies to data files when used in combination with the --schema/-d flag. Assigning values to a CUE path The --path/-l flag can be used to specify a CUE path at which to place a value. Each -l flag specifies either a CUE expression or a CUE field (without the value following the colon), both of which are evaluated within the value. Together, the -l flags specify the path at increasingly deeper nesting. An expression may refer to builtin packages as long as the name can be uniquely identified. The --with-context flag can be used to evaluate the label expression within a struct of contextual data, instead of within the value itself. This struct has the following fields: { // data holds the original source data // (perhaps one of several records in a file). data: _ // filename holds the full path to the file. filename: string // index holds the 0-based index element of the // record within the file. For files containing only // one record, this will be 0. index: uint & =1 } Handling multiple documents or streams To handle multi-document files, such as JSON Lines or YAML files with document separators (---), the user must specify the --path, --list, or --files flag. The --path flag merges each element into a single package as if each element was defined in a separate file. The --list flag concatenates each entry in a file into a list. Using --list flag in combination with the --path flag concatenates entries with the same path into a list, instead of unifying them. Finally, the --files option causes each entry to be written to a different file. The -files flag may only be used in combination with the import command. Examples: # Put a value at a path based on its "kind" and "name" fields. $ cue eval -l 'strings.ToLower(kind)' -l name foo.yaml # Include a schema under the "myschema" field using the path notation. $ cue eval -l myschema: schema: foo.json # Base the path values on its kind and file name. $ cue eval --with-context -l 'path.Base(filename)' -l data.kind foo.yaml `, } var filetypeHelp = &cobra.Command{ Use: "filetypes", Short: "supported file types and qualifiers", Long: `The cue tools supports the following file types: Tag Extensions Description cue .cue CUE source files. json .json JSON files. yaml .yaml/.yml YAML files. toml .toml TOML files jsonl .jsonl/.ndjson Line-separated JSON values. jsonschema JSON Schema. openapi OpenAPI schema. pb Use Protobuf mappings (e.g. json+pb) textproto .textproto Text-based protocol buffers. proto .proto Protocol Buffer definitions. go .go Go source files. text .txt Raw text file; the evaluated value must be of type string. binary Raw binary file; the evaluated value must be of type string or bytes. OpenAPI, JSON Schema and Protocol Buffer definitions are always interpreted as schema. YAML and JSON are always interpreted as data. CUE and Go are interpreted as schema by default, but may be selected to operate in data mode. The cue tool will infer a file's type from its extension by default. The user my override this behavior by using qualifiers. A qualifier takes the form {'+'}':' For instance, cue eval json: foo.data specifies that 'foo.data' should be read as a JSON file. File formats that do not have a default extension may be represented in any data format using the same notation: cue def jsonschema: bar.cue foo.yaml openapi+yaml: baz.def interprets the files bar.cue and foo.yaml as data in the respective formats encoding an JSON Schema, while 'baz.def' is defined to be a YAML file which contents encode OpenAPI definitions. A qualifier applies to all files following it on the command line until the next qualifier. The cue tool does not allow a ':' in filenames. The following tags can be used in qualifiers to further influence input or output. For input these act as restrictions, validating the input. For output these act as filters, showing only the requested data and picking defaults as requested. Tag Description data Require concrete input and output that does not require any evaluation. graph Like data, but allow references. schema Export data and definitions. The following tags are only valid in combination with other tags, and influence the functioning of the codec. The tag they are valid with is mentioned in parentheses at the end. strictFeatures report errors for lossy mappings. (jsonschema) strictKeywords report errors for unknown keywords (jsonschema) strict report errors for either of the above (jsonschema) Many commands also support the --out and --outfile/-o flags. The --out flag specifies the output type using a qualifier (without the ':'). The -o flag specifies an output file possibly prefixed with a qualifier. Examples: # Interpret bar.cue and foo.yaml as OpenAPI data. $ cue def openapi: bar.cue foo.yaml # Write a CUE package as OpenAPI encoded as YAML, using # an alternate file extension. $ cue def -o openapi+yaml:foo.openapi # Print the data for the current package as YAML. $ cue export --out=yaml # Print the string value of the "name" field as a string. $ cue export -e name --out=text # Write the string value of the "name" field to a text file. $ cue export -e name -o=foo.txt # Write the string value of the "name" field to a file foo. $ cue export -e name -o=text:foo `, } var injectHelp = &cobra.Command{ Use: "injection", Short: "inject files or values into specific fields for a build", Long: `Many of the cue commands allow injecting values or selecting files from the command line using the --inject/-t flag. Injecting files A "build" attribute defines a boolean expression that causes a file to only be included in a build if its expression evaluates to true. There may only be a single @if attribute per file and it must appear before a package clause, or before any CUE declarations if there is no package clause. The expression is a subset of CUE consisting only of identifiers and the operators &&, ||, !, where identifiers refer to tags defined by the user on the command line. For example, the following file will only be included in a build if the user includes the flag "-t prod" on the command line. // File prod.cue @if(prod) package foo Ignoring files An "ignore" attribute causes a file to be unconditionally excluded from a build. The @ignore attribute must appear before a package clause or before any other CUE syntax if there is no package clause. For example: @ignore() // This file will be excluded for all purposes. package foo Injecting values The injection mechanism allows values to be injected into fields that are not defined within the scope of a comprehension, list, or optional field and that are marked with a "tag" attribute. For any field of the form field: x @tag(key) an "--inject key=value" flag will modify the field to field: x & "value" By default, the injected value is treated as a string. Alternatively, the "type" option allows a value to be interpreted as an int, number, or bool. For instance, for a field field: x @tag(key,type=int) the flag "-t key=2" modifies the field to field: x & 2 Valid values for type are "int", "number", "bool", and "string". A tag attribute can also define shorthand values, which can be injected into the fields without having to specify the key. For instance, for environment: string @tag(env,short=prod|staging) "-t prod" sets the environment field to the value "prod". It is still possible to specify "-t env=prod" in this case. Use the usual CUE constraints to limit the possible values of a field. For instance environment: "prod" | "staging" @tag(env,short=prod|staging) ensures the user may only specify "prod" or "staging". Tag variables The injection mechanism allows for the injection of system variables: when variable injection is enabled, tags of the form @tag(dir,var=cwd) will inject the named variable (here cwd) into the tag. An explicitly set value for a tag using --inject/-t takes precedence over an available tag variable. The following variables are supported: now current time in RFC3339 format. os OS identifier of the current system. Valid values: aix android darwin dragonfly freebsd illumos ios js (wasm) linux netbsd openbsd plan9 solaris windows arch architecture identifier of the current system. Valid values: 386 amd64 amd64p32 arm armbe arm64 arm64be loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc ppc64 ppc64le riscv riscv64 s390 s390x sparc sparc64 wasm cwd working directory username current username hostname current hostname rand a random 128-bit integer `, } var commandsHelp = &cobra.Command{ Use: "commands", Short: "user-defined commands", Long: `Workflow commands define actions on instances. For example, they may specify how to upload a configuration to Kubernetes. Workflow commands are defined directly in tool files, which are regular CUE files within the same package with a filename ending in _tool.cue. These are typically defined at the module root so that they apply to all instances. Each workflow command consists of one or more tasks. A task may, for example, load or write a file, consult a user on the command line, fetch a web page, and so on. Each task has inputs and outputs. Outputs are typically filled out by the task implementation as the task completes. Inputs of tasks my refer to outputs of other tasks. The cue tool does a static analysis of the configuration and only starts tasks that are fully specified. Upon completion of each task, cue rewrites the instance, filling in the completed task, and reevaluates which other tasks can now start, and so on until all tasks have completed. Available tasks can be found in the package documentation at https://pkg.go.dev/cuelang.org/go/pkg/tool?tab=subdirectories Examples: In this simple example, we define a workflow command called "hello", which declares a single task called "print" which uses "tool/exec.Run" to execute a shell command that echos output to the terminal: $ cat < hello_tool.cue package foo import "tool/exec" city: "Amsterdam" who: *"World" | string @tag(who) // Say hello! command: hello: { print: exec.Run & { cmd: "echo Hello \(who)! Welcome to \(city)." } } EOF We run the "hello" workflow command like this: $ cue cmd hello Hello World! Welcome to Amsterdam. $ cue cmd --inject who=Jan hello Hello Jan! Welcome to Amsterdam. In this example we declare the "prompted" workflow command which has four tasks. The first task prompts the user for a string input. The second task depends on the first, and echos the response back to the user with a friendly message. The third task pipes the output from the second to a file. The fourth task pipes the output from the second to standard output (i.e. it echos it again). package foo import ( "tool/cli" "tool/exec" "tool/file" ) city: "Amsterdam" // Say hello! command: prompter: { // save transcript to this file var: file: *"out.txt" | string @tag(file) ask: cli.Ask & { prompt: "What is your name?" response: string } // starts after ask echo: exec.Run & { cmd: ["echo", "Hello", ask.response + "!"] stdout: string // capture stdout } // starts after echo append: file.Append & { filename: var.file contents: echo.stdout } // also starts after echo print: cli.Print & { text: echo.stdout } } The types of the commands and tasks are defined in CUE itself at cuelang.org/go/pkg/tool/tool.cue. command: [Name]: Command Command: { // Tasks specifies the things to run to complete a command. Tasks are // typically underspecified and completed by the particular internal // handler that is running them. Tasks can be a single task, or a full // hierarchy of tasks. // // Tasks that depend on the output of other tasks are run after such tasks. // Use $after if a task needs to run after another task but does not // otherwise depend on its output. Tasks // $usage summarizes how a command takes arguments. // // Example: // mycmd [-n] names $usage?: string // $short is short description of what the command does. $short?: string // $long is a longer description that spans multiple lines and // likely contain examples of usage of the command. $long?: string } // Tasks defines a hierarchy of tasks. A command completes if all // tasks have run to completion. Tasks: Task | { [name=Name]: Tasks } // Name defines a valid task or command name. Name: =~#"^\PL([-](\PL|\PN))*$"# // A Task defines a step in the execution of a command. Task: { $type: "tool.Task" // legacy field 'kind' still supported for now. // $id indicates the operation to run. It must be of the form // packagePath.Operation. $id: =~#"\."# // $after can be used to specify a task is run after another one, when // it does not otherwise refer to an output of that task. $after?: Task | [...Task] } `, } // indent returns s with all lines indented by one tab. func indent(s string) string { var buf strings.Builder for scan := bufio.NewScanner(strings.NewReader(s)); scan.Scan(); { line := scan.Bytes() if len(line) == 0 { buf.WriteString("\n") continue } buf.WriteString("\t") buf.Write(line) buf.WriteString("\n") } return buf.String() } // TODO: tags // - doc/nodoc // - attr/noattr // - id= // TODO: filetypes: // - binpb cue-lang-cue-db9cc73/cmd/cue/cmd/import.go000066400000000000000000000360431474664451600204310ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "cmp" "fmt" "os" "path/filepath" "strings" "unicode" "github.com/spf13/cobra" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/load" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/encoding/json" "cuelang.org/go/encoding/protobuf" "cuelang.org/go/internal" pkgyaml "cuelang.org/go/pkg/encoding/yaml" ) func newImportCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "import [mode] [inputs]", Short: "convert other formats to CUE files", Long: `import converts other formats, like JSON and YAML to CUE files Files can either be specified explicitly, or inferred from the specified packages. Within packages, import only looks for JSON and YAML files by default (see the "filetypes" help topic for more info). This behavior can be overridden by specifying one of the following modes: Mode Extensions json Look for JSON files (.json .jsonl .ndjson). yaml Look for YAML files (.yaml .yml). toml Look for TOML files (.toml). text Look for text files (.txt). binary Look for files with extensions specified by --ext and interpret them as binary. jsonschema Interpret JSON, YAML or CUE files as JSON Schema. openapi Interpret JSON, YAML or CUE files as OpenAPI. auto Look for JSON or YAML files and interpret them as data, JSON Schema, or OpenAPI, depending on existing fields. data Look for JSON or YAML files and interpret them as data. proto Convert Protocol buffer definition files and transitive dependencies. Using the --ext flag in combination with a mode causes matched files to be interpreted as the format indicated by the mode, overriding any other meaning attributed to that extension. auto mode In auto mode, data files are interpreted based on some marker fields. JSON Schema is identified by a top-level "$schema" field with a URL of the form "https?://json-schema.org/.*schema#?". OpenAPI is identified by the existence of a top-level field "openapi", which must have a major semantic version of 3, and the info.title and info.version fields. proto mode Proto mode converts .proto files containing Prototcol Buffer definitions to CUE. The -I defines the path for includes. The module root is added implicitly if it exists. The package name for a converted file is derived from the go_package option. It can be overridden with the -p flag. A module root must be specified if a .proto files includes other files within the module. Files include from outside the module are also imported and stored within the cue.mod directory. The import path is defined by either the go_package option or, in the absence of this option, the googleapis.com/ convention. The following command imports all .proto files in all subdirectories as well all dependencies. cue import proto -I ../include ./... The module root is implicitly added as an import path. Binary mode Loads matched files as binary. JSON/YAML mode The -f option allows overwriting of existing files. This only applies to files generated for explicitly specified files or files contained in explicitly specified packages. Use the -R option in addition to overwrite files generated for transitive dependencies (files written to cue.mod/gen/...). The -n option is a regexp used to filter file names in the matched package directories. The -I flag is used to specify import paths for proto mode. The module root is implicitly added as an import if it exists. Examples: # Convert individual files: $ cue import foo.json bar.json # create foo.cue and bar.cue # Convert all json files in the indicated directories: $ cue import json ./... The "flags" help topic describes how to assign values to a specific path within a CUE namespace. Some examples of that Examples: $ cat < foo.yaml kind: Service name: booster EOF # include the parsed file as an emit value: $ cue import foo.yaml $ cat foo.cue { kind: Service name: booster } # include the parsed file at the root of the CUE file: $ cue import -f foo.yaml $ cat foo.cue kind: Service name: booster # include the import config at the mystuff path $ cue import -f -l '"mystuff"' foo.yaml $ cat foo.cue myStuff: { kind: Service name: booster } # append another object to the input file $ cat <> foo.yaml --- kind: Deployment name: booster replicas: 1 EOF # base the path values on the input $ cue import -f -l 'strings.ToLower(kind)' -l name foo.yaml $ cat foo.cue service: booster: { kind: "Service" name: "booster" } # base the path values on the input and file name $ cue import -f --with-context -l 'path.Base(filename)' -l data.kind foo.yaml $ cat foo.cue "foo.yaml": Service: { kind: "Service" name: "booster" } "foo.yaml": Deployment: { kind: "Deployment" name: "booster replicas: 1 } # include all files as list elements $ cue import -f --list foo.yaml $ cat foo.cue [{ kind: "Service" name: "booster" }, { kind: "Deployment" name: "booster replicas: 1 }] # collate files with the same path into a list $ cue import -f -list -l 'strings.ToLower(kind)' foo.yaml $ cat foo.cue service: [{ kind: "Service" name: "booster" } deployment: [{ kind: "Deployment" name: "booster replicas: 1 }] Embedded data files The --recursive or -R flag enables the parsing of fields that are string representations of data formats themselves. A field that can be parsed is replaced with a call encoding the data from a structured form that is placed in a sibling field. It is also possible to recursively hoist data formats: Example: $ cat < example.json "a": { "data": '{ "foo": 1, "bar": 2 }', } EOF $ cue import -R example.json $ cat example.cue import "encoding/json" a: { data: json.Encode(_data), _data = { foo: 1 bar: 2 } } `, RunE: mkRunE(c, runImport), } addOutFlags(cmd.Flags(), false) addOrphanFlags(cmd.Flags()) cmd.Flags().Bool(string(flagFiles), false, "split multiple entries into different files") cmd.Flags().Bool(string(flagDryRun), false, "show what files would be created") cmd.Flags().BoolP(string(flagRecursive), "R", false, "recursively parse string values") cmd.Flags().StringArray(string(flagExt), nil, "match files with these extensions") return cmd } // TODO: factor out rooting of orphaned files. func runImport(cmd *Command, args []string) (err error) { c := &config{ fileFilter: `\.(json|yaml|yml|toml|jsonl|ndjson|ldjson)$`, interpretation: build.Auto, loadCfg: &load.Config{DataFiles: true}, } var mode string extensions := flagExt.StringArray(cmd) if len(args) >= 1 && !strings.ContainsAny(args[0], `/\:.`) { c.interpretation = "" if len(extensions) > 0 { c.overrideDefault = true } mode = args[0] args = args[1:] c.encoding = build.Encoding(mode) switch mode { case "proto": c.fileFilter = `\.proto$` case "json": c.fileFilter = `\.(json|jsonl|ndjson|ldjson)$` case "yaml": c.fileFilter = `\.(yaml|yml)$` case "toml": c.fileFilter = `\.toml$` case "text": c.fileFilter = `\.txt$` case "binary": if len(extensions) == 0 { return errors.Newf(token.NoPos, "use of --ext flag required in binary mode") } case "auto", "openapi", "jsonschema": c.interpretation = build.Interpretation(mode) c.encoding = "yaml" case "data": // default mode for encoding/ no interpretation. c.encoding = "" default: return errors.Newf(token.NoPos, "unknown mode %q", mode) } } if len(extensions) > 0 { c.fileFilter = `\.(` + strings.Join(extensions, "|") + `)$` } b, err := parseArgs(cmd, args, c) if err != nil { return err } switch mode { default: err = genericMode(cmd, b) case "proto": err = protoMode(b) } return err } func protoMode(b *buildPlan) error { var prev *build.Instance root := "" module := "" protoFiles := []*build.File{} for _, b := range b.insts { hasProto := false for _, f := range b.OrphanedFiles { if f.Encoding == "proto" { protoFiles = append(protoFiles, f) hasProto = true } } if !hasProto { continue } // check dirs, all must have same root. switch { case root != "": if b.Root != "" && root != b.Root { return errors.Newf(token.NoPos, "instances must have same root in proto mode; "+ "found %q (%s) and %q (%s)", prev.Root, prev.DisplayPath, b.Root, b.DisplayPath) } case b.Root != "": root = b.Root module = b.Module prev = b } } c := &protobuf.Config{ Root: root, Module: module, Paths: b.encConfig.ProtoPath, PkgName: b.encConfig.PkgName, EnumMode: flagProtoEnum.String(b.cmd), } if module != "" { // We only allow imports from packages within the module if an actual // module is allowed. c.Paths = append([]string{root}, c.Paths...) } p := protobuf.NewExtractor(c) for _, f := range protoFiles { _ = p.AddFile(f.Filename, f.Source) } files, err := p.Files() if err != nil { return err } modDir := "" if root != "" { modDir = internal.GenPath(root) } for _, f := range files { // Only write the cue.mod files if they don't exist or if -Rf is used. abs := f.Filename if !filepath.IsAbs(abs) { abs = filepath.Join(root, abs) } force := flagForce.Bool(b.cmd) if flagRecursive.Bool(b.cmd) && strings.HasPrefix(abs, modDir) { force = false } cueFile, err := getFilename(b, f, root, force) if cueFile == "" { return err } err = writeFile(b, f, cueFile) if err != nil { return err } } return nil } func genericMode(cmd *Command, b *buildPlan) error { pkgFlag := flagPackage.String(cmd) for _, pkg := range b.insts { pkgName := cmp.Or(pkgFlag, pkg.PkgName) // TODO: allow if there is a unique package name. if pkgName == "" && len(b.insts) > 1 { return fmt.Errorf("must specify package name with the -p flag") } } for _, f := range b.imported { err := handleFile(b, f) if err != nil { return err } } return nil } func getFilename(b *buildPlan, f *ast.File, root string, force bool) (filename string, err error) { cueFile := cmp.Or(flagOutFile.String(b.cmd), f.Filename) if cueFile != "-" { switch _, err := os.Stat(cueFile); { case os.IsNotExist(err): case err == nil: if !force { // TODO: mimic old behavior: write to stderr, but do not exit // with error code. Consider what is best to do here. stderr := b.cmd.OutOrStderr() if root != "" { cueFile, _ = filepath.Rel(root, cueFile) } fmt.Fprintf(stderr, "Skipping file %q: already exists.\n", filepath.ToSlash(cueFile)) if strings.HasPrefix(cueFile, "cue.mod") { fmt.Fprintln(stderr, "Use -Rf to override.") } else { fmt.Fprintln(stderr, "Use -f to override.") } return "", nil } default: return "", fmt.Errorf("error creating file: %v", err) } } return cueFile, nil } func handleFile(b *buildPlan, f *ast.File) (err error) { // TODO: fill out root. cueFile, err := getFilename(b, f, "", flagForce.Bool(b.cmd)) if cueFile == "" { return err } if flagRecursive.Bool(b.cmd) { h := hoister{fields: map[string]bool{}} h.hoist(f) } return writeFile(b, f, cueFile) } func writeFile(p *buildPlan, f *ast.File, cueFile string) error { if flagDryRun.Bool(p.cmd) { cueFile, err := filepath.Rel(rootWorkingDir, cueFile) if err != nil { return err } stderr := p.cmd.OutOrStderr() fmt.Fprintf(stderr, "importing into %s\n", cueFile) return nil } b, err := format.Node(f, format.Simplify()) if err != nil { return fmt.Errorf("error formatting file: %v", err) } if cueFile == "-" { _, err := p.cmd.OutOrStdout().Write(b) return err } _ = os.MkdirAll(filepath.Dir(cueFile), 0777) return os.WriteFile(cueFile, b, 0666) } type hoister struct { fields map[string]bool } func (h *hoister) hoist(f *ast.File) { ast.Walk(f, nil, func(n ast.Node) { name := "" switch x := n.(type) { case *ast.Field: name, _, _ = ast.LabelName(x.Label) case *ast.Alias: name = x.Ident.Name case *ast.LetClause: name = x.Ident.Name } if name != "" { h.fields[name] = true } }) _ = astutil.Apply(f, func(c astutil.Cursor) bool { n := c.Node() switch n.(type) { case *ast.Comprehension: return false } return true }, func(c astutil.Cursor) bool { switch f := c.Node().(type) { case *ast.Field: name, _, _ := ast.LabelName(f.Label) if name == "" { return false } lit, ok := f.Value.(*ast.BasicLit) if !ok || lit.Kind != token.STRING { return false } str, err := literal.Unquote(lit.Value) if err != nil { return false } expr, enc := tryParse(str) if expr == nil { return false } importIdent := &ast.Ident{ Name: enc, Node: ast.NewImport(nil, "encoding/"+enc), } // found a replaceable string dataField := h.uniqueName(name, "_", "cue_") f.Value = ast.NewCall(ast.NewSel(importIdent, "Marshal"), ast.NewIdent(dataField)) // TODO: use definitions instead c.InsertAfter(astutil.ApplyRecursively(&ast.LetClause{ Ident: ast.NewIdent(dataField), Expr: expr, })) } return true }) astutil.Sanitize(f) } func tryParse(str string) (s ast.Expr, pkg string) { b := []byte(str) if json.Valid(b) { expr, err := parser.ParseExpr("", b) if err != nil { // TODO: report error return nil, "" } switch expr.(type) { case *ast.StructLit, *ast.ListLit: default: return nil, "" } return expr, "json" } // When a string has no newlines, never treat it as // YAML because there's too much risk of false positives // with regular-expressions or other such syntax. // See issue 1443. if bytes.IndexByte(b, '\n') == -1 { return nil, "" } // TODO(mvdan): move from pkg/encoding/yaml to encoding/yaml. if expr, err := pkgyaml.Unmarshal(b); err == nil { switch expr.(type) { case *ast.StructLit, *ast.ListLit: default: return nil, "" } return expr, "yaml" } return nil, "" } func (h *hoister) uniqueName(base, prefix, typ string) string { base = strings.Map(func(r rune) rune { if unicode.In(r, unicode.L, unicode.N) { return r } return '_' }, base) name := prefix + typ + base for { if !h.fields[name] { h.fields[name] = true return name } name = prefix + typ + base typ += "x" } } cue-lang-cue-db9cc73/cmd/cue/cmd/integration/000077500000000000000000000000001474664451600211055ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/integration/base/000077500000000000000000000000001474664451600220175ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/integration/base/base_test.go000066400000000000000000000014451474664451600243230ustar00rootroot00000000000000//go:build !windows package feature import ( "testing" "cuelang.org/go/internal/golangorgx/gopls/hooks" . "cuelang.org/go/internal/golangorgx/gopls/test/integration" "cuelang.org/go/internal/golangorgx/gopls/test/integration/fake" "github.com/go-quicktest/qt" ) func TestMain(m *testing.M) { Main(m, hooks.Options) } func TestFormatFile(t *testing.T) { const files = ` -- cue.mod/module.cue -- module: "mod.example" language: version: "v0.10.0" -- foo.cue -- package foo // this is a test ` Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("foo.cue") env.EditBuffer("foo.cue", fake.NewEdit(0, 0, 1, 0, "package bar\n")) env.FormatBuffer("foo.cue") got := env.BufferText("foo.cue") want := "package bar\n\n// this is a test\n" qt.Assert(t, qt.Equals(got, want)) }) } cue-lang-cue-db9cc73/cmd/cue/cmd/integration/workspace/000077500000000000000000000000001474664451600231035ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/integration/workspace/workspace_folders_test.go000066400000000000000000000066061474664451600302150ustar00rootroot00000000000000//go:build !windows package workspace import ( "fmt" "path/filepath" "testing" "cuelang.org/go/internal/golangorgx/gopls/hooks" . "cuelang.org/go/internal/golangorgx/gopls/test/integration" "cuelang.org/go/internal/golangorgx/gopls/test/integration/fake" "github.com/go-quicktest/qt" ) func TestMain(m *testing.M) { Main(m, hooks.Options) } // TestWorkingSimpleModule ensures that we have a successful package load for a // simple module rooted in the workspace folder with a single CUE file at the // root. func TestWorkingSimpleModule(t *testing.T) { const files = ` -- cue.mod/module.cue -- module: "mod.example" language: { version: "v0.11.0" } -- a.cue -- package a -- b/b.cue -- package c ` WithOptions().Run(t, files, func(t *testing.T, env *Env) { // Simulate a change and ensure we get diagnostics back env.OpenFile("a.cue") env.EditBuffer("a.cue", fake.NewEdit(1, 0, 1, 0, "\nx: 5\n")) got := env.BufferText("a.cue") want := "package a\n\nx: 5\n" qt.Assert(t, qt.Equals(got, want)) env.Await(env.DoneWithChange()) }) } // TestMultipleWorkspaceFolders verifies the behaviour of starting 'cue lsp' // with multiple WorkspaceFolders. This is currently not supported, and hence // the test is a negative test that asserts 'cue lsp' will fail (during the // Initialize phase). func TestMultipleWorkspaceFolders(t *testing.T) { const files = ` -- a/cue.mod/module.cue -- module: "mod.example/b" language: version: "v0.11.0" -- a/a.cue -- package a -- b/cue.mod/module.cue -- module: "mod.example/b" language: version: "v0.11.0" -- b/b.cue -- package a ` WithOptions( WorkspaceFolders("a", "b"), InitializeError("initialize: got 2 WorkspaceFolders; expected 1"), ).Run(t, files, nil) } // TODO(myitcv): add a test that verifies we get an error in the case that a // .cue file is opened "standalone", i.e. outside of the context of a workspace // folder. This is possible in VSCode at least. We currently implement the // error handling in vscode-cue in that instance but perhaps it should live in // 'cue lsp'. // TestNoContainingModule verifies that user is shown an error message in the // case that they open a .cue file in the context of a workspace folder where // the workspace folder does not correspond to the root of a CUE module. In // this case there is simply no CUE module. func TestNoContainingModule(t *testing.T) { const files = ` -- a.cue -- package a ` WithOptions().Run(t, files, func(t *testing.T, env *Env) { want := fmt.Sprintf("WorkspaceFolder %s does not correspond to a CUE module", env.Sandbox.Workdir.RootURI().Path()) env.Await(ShownMessage(want)) }) } // TestNoContainingModule verifies that user is shown an error message in the // case that they open a .cue file in the context of a workspace folder where // the workspace folder does not correspond to the root of a CUE module. In // this case, the parent directory corresponds to the root of CUE module, but // the workspace folder itself corresponds to a subdirectory in the CUE module. func TestWorkspaceFolderWithCUEModInParent(t *testing.T) { const files = ` -- cue.mod/module.cue -- -- a/a.cue -- package a ` WithOptions( WorkspaceFolders("a"), ).Run(t, files, func(t *testing.T, env *Env) { workspaceFolder := filepath.Join(env.Sandbox.Workdir.RootURI().Path(), "a") want := fmt.Sprintf("WorkspaceFolder %s does not correspond to a CUE module", workspaceFolder) env.Await(ShownMessage(want)) }) } cue-lang-cue-db9cc73/cmd/cue/cmd/login.go000066400000000000000000000146131474664451600202260ustar00rootroot00000000000000// Copyright 2023 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "context" "fmt" "net/http" "os" "strings" "time" "github.com/spf13/cobra" "golang.org/x/oauth2" "cuelang.org/go/internal/cueconfig" "cuelang.org/go/internal/httplog" "cuelang.org/go/internal/mod/modresolve" ) // TODO: We need a testscript to cover "cue login" with its oauth2 device flow. // Perhaps with a small net/http/httptest server to mock the basics of the oauth2 flow? // // It should also test edge cases like: // * succeed whether or not a keychain is available // * load either plaintext or encrypted files, preferring the encrypted one // * existing login entries are kept when adding a new one // * using the well-known endpoint to locate oauth2 endpoints // * obtaining a new access token when it expires via the refresh token, and store the refreshed one // * asking the user to re-run "cue login" if the access token expires without a refresh token // * registry strings with a path prefix or an insecure option // // We will have end-to-end tests which will cover authentication with registry.cue.works, // but they will use an existing token stored as a secret to avoid the human device flow in "cue login". func newLoginCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "login [registry]", Short: "log into a CUE registry", Long: `WARNING: THIS COMMAND IS EXPERIMENTAL. Log into a CUE registry via the OAuth 2.0 Device Authorization Grant. Without an argument, CUE_REGISTRY is used if it points to a single registry. Use the --token flag to provide a token generated via the web interface, removing the need for a human to interact with the OAuth device flow. Once the authorization is successful, a token is stored in a logins.json file inside $CUE_CONFIG_DIR; see 'cue help environment'. `, Args: cobra.MaximumNArgs(1), RunE: mkRunE(c, func(cmd *Command, args []string) error { var locResolver modresolve.LocationResolver var err error if len(args) > 0 { locResolver, err = modresolve.ParseCUERegistry(args[0], "") if err != nil { return err } } else { locResolver, err = getRegistryResolver() if err != nil { return err } } registryHosts := locResolver.AllHosts() if len(registryHosts) > 1 { return fmt.Errorf("need a single CUE registry to log into") } // TODO(mvdan): should we refuse to log into a CUE registry where host.Insecure==true? // It is useful for local testing or debugging, but is otherwise pretty dangerous. host := registryHosts[0] loginsPath, err := cueconfig.LoginConfigPath(os.Getenv) if err != nil { return fmt.Errorf("cannot find the path to store CUE registry logins: %v", err) } var tok *oauth2.Token switch tokenStr := flagToken.String(cmd); { case tokenStr == "": // By default, we perform the OAuth 2.0 device flow to obtain a new token. // Note that we refuse to continue if the user set --token="", // because that can be an easy mistake to make via --token=${UNSET_VAR}. if flagToken.IsSet(cmd) { return fmt.Errorf("the --token flag needs a non-empty string") } ctx := backgroundContext() // Cause the oauth2 logic to log HTTP requests when logging is enabled. ctx = context.WithValue(ctx, oauth2.HTTPClient, &http.Client{ Transport: httpTransport(), }) // Elide request and response bodies because they're likely to include sensitive information. ctx = httplog.RedactRequestBody(ctx, "request body can contain sensitive data when logging in") ctx = httplog.RedactResponseBody(ctx, "response body can contain sensitive data when logging in") oauthCfg := cueconfig.RegistryOAuthConfig(host) resp, err := oauthCfg.DeviceAuth(ctx) if err != nil { return fmt.Errorf("cannot start the OAuth2 device flow: %v", err) } // TODO: we could try using $BROWSER or xdg-open here, // falling back to the text instructions below fmt.Printf("Enter the code %s via: %s\n", resp.UserCode, resp.VerificationURI) fmt.Printf("Or just open: %s\n", resp.VerificationURIComplete) fmt.Println() tok, err = oauthCfg.DeviceAccessToken(ctx, resp) if err != nil { return fmt.Errorf("cannot obtain the OAuth2 token: %v", err) } case strings.HasPrefix(tokenStr, "appv1_"): // appv1 tokens generated by the CUE registry are valid for one year. // The token string itself does not contain the expiry timestamp, // so we don't store any such timestamp in the logins.json file. tok = &oauth2.Token{AccessToken: tokenStr} case tokenStr == "stdin", tokenStr == "clipboard": // Since tokens easily get long and hard to input or paste directly, // other tools support password or token flags which accept stdin. // Reserve special token strings to consume stdin or the clipboard. fallthrough default: // For now, reject any unknown token formats. // We could consider handling any arbitrary access tokens just like // we do appv1, only storing the access token and nothing else, // but for now that doesn't seem to be necessary. return fmt.Errorf("unknown token format, expected an appv1_ prefix") } // For consistency, store timestamps in UTC. tok.Expiry = tok.Expiry.UTC() // OAuth2 measures expiry in seconds via the expires_in JSON wire format field, // so any sub-second units add unnecessary verbosity. tok.Expiry = tok.Expiry.Truncate(time.Second) _, err = cueconfig.UpdateRegistryLogin(loginsPath, host.Name, tok) if err != nil { return fmt.Errorf("cannot store CUE registry logins: %v", err) } fmt.Printf("Login for %s stored in %s\n", host.Name, loginsPath) // TODO: Once we support encryption, we should print a warning if it's not available. return nil }), } cmd.Flags().String(string(flagToken), "", "provide an access token rather than starting the OAuth device flow") return cmd } const ( flagToken flagName = "token" ) cue-lang-cue-db9cc73/cmd/cue/cmd/lsp.go000066400000000000000000000031431474664451600177100ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "context" goplscmd "cuelang.org/go/internal/golangorgx/gopls/cmd" "cuelang.org/go/internal/golangorgx/gopls/hooks" "cuelang.org/go/internal/golangorgx/tools/tool" "github.com/spf13/cobra" ) func newLSPCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Hidden: true, Use: "lsp", Short: "start or interact with a CUE Language Server instance", Run: func(cmd *cobra.Command, args []string) { c.Command = cmd runLSP(c, args) }, DisableFlagParsing: true, } // TODO(myitcv): flesh out docs. // TODO(myitcv): move the LSP towards the same flag processing as used here // in cmd/cue. // TODO(myitcv): add some means for 'cue help lsp' triggering 'cue lsp // -help' until such time as we flip the LSP command itself over to cobra // (if that's what we want to do). // TODO(myitcv): prevent the 'lsp' command from inheriting the root flags. return cmd } func runLSP(cmd *Command, args []string) { ctx := context.Background() tool.Main(ctx, goplscmd.New(hooks.Options), args) } cue-lang-cue-db9cc73/cmd/cue/cmd/mod.go000066400000000000000000000032341474664451600176720ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "github.com/spf13/cobra" ) func newModCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "mod [arguments]", Short: "module maintenance", Long: `Mod groups commands which operate on CUE modules. Note that support for modules is built into all the cue commands, not just 'cue mod'. See also: cue help modules `, RunE: mkRunE(c, func(cmd *Command, args []string) error { stderr := cmd.Stderr() if len(args) == 0 { fmt.Fprintln(stderr, "mod must be run as one of its subcommands") } else { fmt.Fprintf(stderr, "mod must be run as one of its subcommands: unknown subcommand %q\n", args[0]) } fmt.Fprintln(stderr, "Run 'cue help mod' for known subcommands.") return ErrPrintedError }), } cmd.AddCommand(newModEditCmd(c)) cmd.AddCommand(newModFixCmd(c)) cmd.AddCommand(newModGetCmd(c)) cmd.AddCommand(newModInitCmd(c)) cmd.AddCommand(newModRegistryCmd(c)) cmd.AddCommand(newModRenameCmd(c)) cmd.AddCommand(newModResolveCmd(c)) cmd.AddCommand(newModTidyCmd(c)) cmd.AddCommand(newModUploadCmd(c)) return cmd } cue-lang-cue-db9cc73/cmd/cue/cmd/modedit.go000066400000000000000000000146651474664451600205520ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "fmt" "os" "strconv" "cuelang.org/go/internal/cueversion" "cuelang.org/go/internal/mod/semver" "cuelang.org/go/mod/modfile" "cuelang.org/go/mod/module" "github.com/spf13/cobra" "github.com/spf13/pflag" ) func newModEditCmd(c *Command) *cobra.Command { editCmd := &modEditCmd{} cmd := &cobra.Command{ Use: "edit", Short: "edit cue.mod/module.cue", Long: `Edit provides a command-line interface for editing cue.mod/module.cue. It reads only that file; it does not look up information about the modules involved. The editing flags specify a sequence of editing operations. The -require=path@version and -drop-require=path@majorversion flags add and drop a requirement on the given module path and version. Note that -require overrides any existing requirements on path. These flags are mainly for tools that understand the module graph. Users should prefer 'cue mod get path@version' which makes other cue.mod adjustments as needed to satisfy constraints imposed by other modules. The --module flag changes the module's path (the module.cue file's module field). The --source flag changes the module's declared source. The --drop-source flag removes the source field. Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, editCmd.run), Args: cobra.ExactArgs(0), } addFlagVar(cmd, flagFunc(editCmd.flagSource), string(flagSource), "set the source field") addFlagVar(cmd, boolFlagFunc(editCmd.flagDropSource), "drop-source", "remove the source field") addFlagVar(cmd, flagFunc(editCmd.flagLanguageVersion), string(flagLanguageVersion), "set language.version ('current' means current language version)") addFlagVar(cmd, flagFunc(editCmd.flagModule), "module", "set the module path") addFlagVar(cmd, flagFunc(editCmd.flagRequire), "require", "add a required module@version") addFlagVar(cmd, flagFunc(editCmd.flagDropRequire), "drop-require", "remove a requirement") return cmd } type modEditCmd struct { edits []func(*modfile.File) error } func (c *modEditCmd) run(cmd *Command, args []string) error { modPath, mf, data, err := readModuleFile() if err != nil { return err } for _, edit := range c.edits { if err := edit(mf); err != nil { return err } } newData, err := mf.Format() if err != nil { return fmt.Errorf("invalid resulting module.cue file after edits: %v", err) } if bytes.Equal(newData, data) { return nil } if err := os.WriteFile(modPath, newData, 0o666); err != nil { return err } return nil } func (c *modEditCmd) addEdit(f func(*modfile.File) error) { c.edits = append(c.edits, f) } func (c *modEditCmd) flagSource(arg string) error { src := &modfile.Source{ Kind: arg, } if err := src.Validate(); err != nil { return err } c.addEdit(func(f *modfile.File) error { f.Source = src return nil }) return nil } func (c *modEditCmd) flagDropSource(arg bool) error { if !arg { return fmt.Errorf("cannot set --drop-source to false") } c.addEdit(func(f *modfile.File) error { f.Source = nil return nil }) return nil } func (c *modEditCmd) flagLanguageVersion(arg string) error { editFunc, err := addLanguageVersion(arg) if err != nil { return err } c.addEdit(editFunc) return nil } func addLanguageVersion(v string) (func(*modfile.File) error, error) { if v == "current" { v = cueversion.LanguageVersion() } else { if semver.Canonical(v) != v { return nil, fmt.Errorf("language version %q is not canonical (must include major, minor and patch versions)", v) } if min := modfile.EarliestClosedSchemaVersion(); semver.Compare(v, min) < 0 { // TODO(rogpeppe) We might want to relax this to allow people to // declare an earlier language version (see https://cuelang.org/issue/3145). return nil, fmt.Errorf("language version %q is too early for module.cue schema (earliest allowed is %s)", v, min) } if max := cueversion.LanguageVersion(); semver.Compare(v, max) > 0 { return nil, fmt.Errorf("language version %q may not be after current language version %s", v, max) } } return func(f *modfile.File) error { if f.Language == nil { f.Language = &modfile.Language{} } f.Language.Version = v return nil }, nil } func (c *modEditCmd) flagModule(arg string) error { if err := module.CheckPath(arg); err != nil { return err } c.addEdit(func(f *modfile.File) error { f.Module = arg return nil }) return nil } func (c *modEditCmd) flagRequire(arg string) error { v, err := module.ParseVersion(arg) if err != nil { return err } c.addEdit(func(f *modfile.File) error { if f.Deps == nil { f.Deps = make(map[string]*modfile.Dep) } vm := v.Path() dep := f.Deps[vm] if dep == nil { dep = &modfile.Dep{} f.Deps[vm] = dep } dep.Version = v.Version() return nil }) return nil } func (c *modEditCmd) flagDropRequire(arg string) error { if err := module.CheckPath(arg); err != nil { return err } // TODO allow dropping a requirement without specifying // the major version - we can use the default field to disambiguate. c.addEdit(func(f *modfile.File) error { delete(f.Deps, arg) return nil }) return nil } func addFlagVar(cmd *cobra.Command, v pflag.Value, name string, usage string) { flags := cmd.Flags() flags.Var(v, name, usage) // This works around https://github.com/spf13/pflag/issues/281 if v, ok := v.(interface{ IsBoolFlag() bool }); ok && v.IsBoolFlag() { flags.Lookup(name).NoOptDefVal = "true" } } type flagFunc func(string) error func (f flagFunc) String() string { return "" } func (f flagFunc) Set(s string) error { return f(s) } func (f flagFunc) Type() string { return "string" } type boolFlagFunc func(bool) error func (f boolFlagFunc) String() string { return "" } func (f boolFlagFunc) Set(s string) error { b, err := strconv.ParseBool(s) if err != nil { return err } return f(b) } func (f boolFlagFunc) Type() string { return "bool" } func (f boolFlagFunc) IsBoolFlag() bool { return true } cue-lang-cue-db9cc73/cmd/cue/cmd/modfix.go000066400000000000000000000037441474664451600204070ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "fmt" "os" "path/filepath" "cuelang.org/go/mod/modfile" "github.com/spf13/cobra" ) func newModFixCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "fix", Short: "fix a legacy cue.mod/module.cue file", Long: `Fix provides a way to migrate from a legacy module.cue file to the new standard syntax. It - adds a language.version field - moves unrecognized fields into the custom.legacy field - adds a major version to the module path If there is no module path, it chooses an arbitrary path (test.example@v0). If the module.cue file is already compatible with the new syntax, it is just formatted without making any other changes. Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, runModFix), Args: cobra.ExactArgs(0), } return cmd } func runModFix(cmd *Command, args []string) error { modRoot, err := findModuleRoot() if err != nil { return err } modPath := filepath.Join(modRoot, "cue.mod", "module.cue") data, err := os.ReadFile(modPath) if err != nil { return err } mf, err := modfile.FixLegacy(data, modPath) if err != nil { return err } newData, err := mf.Format() if err != nil { return fmt.Errorf("internal error: invalid module.cue file generated: %v", err) } if bytes.Equal(newData, data) { return nil } if err := os.WriteFile(modPath, newData, 0o666); err != nil { return err } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/modget.go000066400000000000000000000107121474664451600203710ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "context" "fmt" "os" "path/filepath" "github.com/spf13/cobra" "cuelang.org/go/internal/httplog" "cuelang.org/go/internal/mod/modload" "cuelang.org/go/mod/modfile" ) func newModGetCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "get", Short: "add and upgrade module dependencies", Long: `Get updates module dependencies, fetching new dependencies if needed and changing versions to specified versions. It can downgrade a version only when a higher version is not required by other dependencies. Each argument specifies a module path and optionally a version suffix. If there is no version suffix, the latest non-prerelease version of the module will be requested; alternatively a suffix of "@latest" also specifies the latest version. A version suffix can contain a major version only (@v1), a major and minor version (@v1.2) or full version (@v1.2.3). If minor or patch version is omitted, the latest non-prerelease version will be chosen that has the same major and minor versions. If the desired version cannot be chosen (for example because a dependency already uses a later version than the desired version), this command will fail. See "cue help environment" for details on how $CUE_REGISTRY is used to determine the modules registry. Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, runModGet), Args: cobra.MinimumNArgs(1), } return cmd } func runModGet(cmd *Command, args []string) error { reg, err := getCachedRegistry() if err != nil { return err } ctx := backgroundContext() modRoot, err := findModuleRoot() if err != nil { return err } mf, err := modload.UpdateVersions(ctx, os.DirFS(modRoot), ".", reg, args) if err != nil { return suggestModCommand(err) } // TODO check whether it's changed or not. data, err := mf.Format() if err != nil { return fmt.Errorf("internal error: invalid module.cue file generated: %v", err) } modPath := filepath.Join(modRoot, "cue.mod", "module.cue") oldData, err := os.ReadFile(modPath) if err != nil { // Shouldn't happen because modload.Load returns an error // if it can't load the module file. return err } if bytes.Equal(data, oldData) { return nil } if err := os.WriteFile(modPath, data, 0o666); err != nil { return err } return nil } func readModuleFile() (string, *modfile.File, []byte, error) { modRoot, err := findModuleRoot() if err != nil { return "", nil, nil, err } modPath := filepath.Join(modRoot, "cue.mod", "module.cue") data, err := os.ReadFile(modPath) if err != nil { return "", nil, nil, err } mf, err := modfile.ParseNonStrict(data, modPath) if err != nil { return "", nil, nil, err } return modPath, mf, data, nil } func findModuleRoot() (string, error) { // TODO this logic is duplicated in multiple places. We should // consider deduplicating it. dir := rootWorkingDir for { if _, err := os.Stat(filepath.Join(dir, "cue.mod")); err == nil { return dir, nil } else if !os.IsNotExist(err) { return "", err } dir1 := filepath.Dir(dir) if dir1 == dir { return "", fmt.Errorf("module root not found") } dir = dir1 } } func backgroundContext() context.Context { // TODO move this into the ociregistry module return httplog.ContextWithAllowedURLQueryParams( context.Background(), allowURLQueryParam, ) } // The set of query string keys that we expect to send as part of the OCI // protocol. Anything else is potentially dangerous to leak, as it's probably // from a redirect. These redirects often included tokens or signed URLs. // TODO move this into the ociregistry module. var paramAllowlist = map[string]bool{ // Token exchange "scope": true, "service": true, // Cross-repo mounting "mount": true, "from": true, // Layer PUTerror "digest": true, // Listing tags and catalog "n": true, "last": true, } func allowURLQueryParam(k string) bool { return paramAllowlist[k] } cue-lang-cue-db9cc73/cmd/cue/cmd/modinit.go000066400000000000000000000055241474664451600205620ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "os" "path/filepath" "github.com/spf13/cobra" "cuelang.org/go/mod/modfile" "cuelang.org/go/mod/module" ) func newModInitCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "init [module]", Short: "initialize new module in current directory", Long: `Init initializes a cue.mod directory in the current directory, in effect creating a new module rooted at the current directory. The cue.mod directory must not already exist. A legacy cue.mod file in the current directory is moved to the new subdirectory. If the module name is not provided, a default module path (cue.example) will be used. `, RunE: mkRunE(c, runModInit), } cmd.Flags().BoolP(string(flagForce), "f", false, "force moving old-style cue.mod file") cmd.Flags().String(string(flagSource), "", "set the source field") cmd.Flags().String(string(flagLanguageVersion), "current", "set the language version ('current' means current language version)") return cmd } func runModInit(cmd *Command, args []string) (err error) { modulePath := "cue.example" if len(args) > 0 { if len(args) != 1 { return fmt.Errorf("too many arguments") } modulePath = args[0] if err := module.CheckPath(modulePath); err != nil { return err } } mod := filepath.Join(rootWorkingDir, "cue.mod") if info, err := os.Stat(mod); err == nil { if !info.IsDir() { return fmt.Errorf("cue.mod files are no longer supported; use cue.mod/module.cue") } return fmt.Errorf("cue.mod directory already exists") } mf := &modfile.File{ Module: modulePath, } if s := flagSource.String(cmd); s != "" { mf.Source = &modfile.Source{ Kind: s, } if err := mf.Source.Validate(); err != nil { return err } } editFunc, err := addLanguageVersion(flagLanguageVersion.String(cmd)) if err != nil { return err } if err := editFunc(mf); err != nil { return err } err = os.Mkdir(mod, 0777) if err != nil && !os.IsExist(err) { return err } data, err := mf.Format() if err != nil { return err } if err := os.WriteFile(filepath.Join(mod, "module.cue"), data, 0o666); err != nil { return err } if err = os.Mkdir(filepath.Join(mod, "usr"), 0777); err != nil { return err } if err = os.Mkdir(filepath.Join(mod, "pkg"), 0777); err != nil { return err } return err } cue-lang-cue-db9cc73/cmd/cue/cmd/modpublish.go000066400000000000000000000461041474664451600212640ustar00rootroot00000000000000// Copyright 2023 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "archive/zip" "bytes" "context" "encoding/json" "errors" "fmt" "io" "io/fs" "os" "path/filepath" "slices" "strings" "sync" "cuelabs.dev/go/oci/ociregistry" "cuelabs.dev/go/oci/ociregistry/ociref" "github.com/opencontainers/go-digest" ocispecroot "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/cobra" "cuelang.org/go/internal/mod/modload" "cuelang.org/go/internal/mod/semver" "cuelang.org/go/internal/vcs" "cuelang.org/go/mod/modconfig" "cuelang.org/go/mod/modfile" "cuelang.org/go/mod/modregistry" "cuelang.org/go/mod/module" "cuelang.org/go/mod/modzip" ) func newModUploadCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "publish ", Short: "publish the current module to a registry", Long: `Publish the current module to an OCI registry. It consults $CUE_REGISTRY to determine where the module should be published (see "cue help environment" for details). Also note that this command does no dependency or other checks at the moment. When the --dry-run flag is specified, nothing will actually be written to a registry, but all other checks will take place. The --json flag can be used to find out more information about the upload. The --out flag can be used to write the module's contents to a directory in OCI Image Layout format. See this link for more details on the format: https://github.com/opencontainers/image-spec/blob/8f3820ccf8f65db8744e626df17fe8a64462aece/image-layout.md Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, runModUpload), Args: cobra.ExactArgs(1), } cmd.Flags().BoolP(string(flagDryRun), "n", false, "only run simulation") cmd.Flags().Bool(string(flagJSON), false, "print verbose information in JSON format (implies --dry-run)") cmd.Flags().String(string(flagOut), "", "write module contents to specified directory in OCI Image Layout format (implies --dry-run)") return cmd } // publishInfo defines the format of the JSON printed by `cue mod publish --json`. type publishInfo struct { Version string `json:"version"` Ref string `json:"ref"` Insecure bool `json:"insecure,omitempty"` Files []string `json:"files"` // TODO include metadata too. } func runModUpload(cmd *Command, args []string) error { ctx := cmd.Context() resolver0, err := getRegistryResolver() if err != nil { return err } dryRun := flagDryRun.Bool(cmd) outDir := flagOut.String(cmd) useJSON := flagJSON.Bool(cmd) if outDir != "" || useJSON { dryRun = true } resolver := &publishRegistryResolverShim{ resolver: resolver0, outDir: flagOut.String(cmd), dryRun: dryRun, // recording the files is somewhat heavyweight, so only do it // if we're going to need them. recordFiles: useJSON, } modRoot, err := findModuleRoot() if err != nil { return err } // Ensure that the module is tidy before publishing it. // TODO: can we use modload.CheckTidy on the already-parsed modfile.File below? // TODO: we might want to provide a "force" flag to skip this check, // particularly for cases where one has private deps or pushes to a custom registry. reg, err := getCachedRegistry() if err != nil { return err } if err := modload.CheckTidy(ctx, os.DirFS(modRoot), ".", reg); err != nil { return suggestModCommand(err) } modPath := filepath.Join(modRoot, "cue.mod/module.cue") modfileData, err := os.ReadFile(modPath) if err != nil { return err } mf, err := modfile.Parse(modfileData, modPath) if err != nil { return err } if !semver.IsValid(args[0]) { return fmt.Errorf("invalid publish version %q; must be valid semantic version (see http://semver.org)", args[0]) } if semver.Canonical(args[0]) != args[0] { return fmt.Errorf("publish version %q is not in canonical form", args[0]) } if major := mf.MajorVersion(); semver.Major(args[0]) != major { if _, _, ok := module.SplitPathVersion(mf.Module); ok { return fmt.Errorf("publish version %q does not match the major version %q declared in %q; must be %s.N.N", args[0], major, modPath, major) } else { return fmt.Errorf("publish version %q does not match implied major version %q in %q; must be %s.N.N", args[0], major, modPath, major) } } mv, err := module.NewVersion(mf.QualifiedModule(), args[0]) if err != nil { return fmt.Errorf("cannot form module version: %v", err) } if mf.Source == nil { // The source field started being a requirement to publish modules in v0.9.0-alpha.2. // For backwards compatibility with existing modules which were already being published, // we assume that any earlier version means "self", mimicking the old behavior. // TODO: perhaps some of this logic, or at least the alpha.2 version, should be in modfile. if semver.Compare(mf.Language.Version, "v0.9.0-alpha.2") < 0 { mf.Source = &modfile.Source{Kind: "self"} } else { // TODO print filename relative to current directory return fmt.Errorf("no source field found in cue.mod/module.cue") } } zf, err := os.CreateTemp("", "cue-publish-") if err != nil { return err } defer os.Remove(zf.Name()) defer zf.Close() // TODO verify that all dependencies exist in the registry. var meta *modregistry.Metadata switch mf.Source.Kind { case "self": if err := modzip.CreateFromDir(zf, mv, modRoot); err != nil { return err } default: vcsImpl, err := vcs.New(mf.Source.Kind, modRoot) if err != nil { return err } status, err := vcsImpl.Status(ctx, modRoot) if err != nil { return err } if status.Uncommitted { // TODO implement --force to bypass this check return fmt.Errorf("VCS state is not clean") } files, err := vcsImpl.ListFiles(ctx, modRoot) if err != nil { return err } archive := make([]pathAbsPair, len(files)) for i, f := range files { archive[i] = pathAbsPair{ path: f, abs: filepath.Join(modRoot, f), } } // Do we have a LICENSE at the root of the module? If not try to grab one // from the root of the VCS repo, first ensuring that git is clean with // respect to that file too. // // TODO: work out whether we can/should consider alternative spellings of // "LICENSE" here. For example with .txt extensions. For context // https://go.dev/ref/mod#vcs-license says: // // This special case allows the same LICENSE file to apply to all modules // within a repository. This only applies to files named LICENSE // specifically, without extensions like .txt. Unfortunately, this cannot // be extended without breaking cryptographic sums of existing modules; // see Authenticating modules. Other tools and websites like pkg.go.dev // may recognize files with other names. // // https://pkg.go.dev/golang.org/x/pkgsite/internal/licenses#pkg-variables // has a much longer list of files. haveLICENSE := slices.Contains(files, "LICENSE") if !haveLICENSE && modRoot != vcsImpl.Root() { licenseFile, err := rootLICENSEFile(ctx, vcsImpl) if err != nil { return err } if licenseFile != "" { archive = append(archive, pathAbsPair{ path: "LICENSE", abs: licenseFile, }) } } if err := modzip.Create(zf, mv, archive, pathAbsPairIO{}); err != nil { return err } meta = &modregistry.Metadata{ VCSType: mf.Source.Kind, VCSCommit: status.Revision, VCSCommitTime: status.CommitTime, } } info, err := zf.Stat() if err != nil { return err } rclient := modregistry.NewClientWithResolver(resolver) if err := rclient.PutModuleWithMetadata(backgroundContext(), mv, zf, info.Size(), meta); err != nil { return fmt.Errorf("cannot put module: %v", err) } ref := ociref.Reference{ Host: resolver.registryName, Repository: resolver.repository, Tag: resolver.tag, Digest: resolver.manifestDigest, } if outDir != "" { if err := resolver.writeIndex(); err != nil { return err } } // Do not output full OCI references by default without --json, as sources // like git may cause non-deterministic digests due to commit hashes // including timestamps. Most users shouldn't care about full digests in // most cases, and any non-determinism causes issues for reproducible guides // such as those under cuelang.org. // // TODO: implement -v or similar to include the full ociref.Reference form. switch { case useJSON: info := publishInfo{ Version: mv.String(), Ref: ref.String(), Insecure: resolver.insecure, Files: resolver.files, } data, err := json.MarshalIndent(info, "", "\t") if err != nil { return err } data = append(data, '\n') os.Stdout.Write(data) case outDir != "": fmt.Printf("wrote image for %s to %s\n", mv, outDir) case dryRun: // See comment above about short vs regular OCI reference output. fmt.Printf("dry-run published %s to %v\n", mv, shortString(ref)) default: // See comment above about short vs regular OCI reference output. fmt.Printf("published %s to %v\n", mv, shortString(ref)) } return nil } // rootLICENSEFile returns the absolute path of a LICENSE file if one // exists under the control of vcsImpl, and that file is "clean" with // respect to the current commit. If no LICENSE file exists, then an // empty string is returned. func rootLICENSEFile(ctx context.Context, vcsImpl vcs.VCS) (string, error) { licenseFile := filepath.Join(vcsImpl.Root(), "LICENSE") // relLicenseFile is used in a couple of error situations below relLicenseFile := func() string { rel, err := filepath.Rel(rootWorkingDir, licenseFile) if err == nil { return rel } return licenseFile } licenseFileInfo, err := os.Lstat(licenseFile) if err != nil { // If the LICENSE file does not exist, this is not an error. We just // have nothing to include. if errors.Is(err, os.ErrNotExist) { return "", nil } return "", err } if !licenseFileInfo.Mode().IsRegular() { return "", fmt.Errorf("%s is not a regular file", relLicenseFile()) } // Verify that the LICENSE file is "clean" with respect to the commit status, err := vcsImpl.Status(ctx, licenseFile) if err != nil { return "", err } if status.Uncommitted { return "", fmt.Errorf("VCS state is not clean for %s", relLicenseFile()) } return licenseFile, nil } // shortString returns a shortened form of an OCI reference, basically // [ociref.Reference.String] minus the trailing digest. The code implementation // is a copy-paste with exactly that adaptation. func shortString(ref ociref.Reference) string { var buf strings.Builder buf.Grow(len(ref.Host) + 1 + len(ref.Repository) + 1 + len(ref.Tag)) if ref.Host != "" { buf.WriteString(ref.Host) buf.WriteByte('/') } buf.WriteString(ref.Repository) if len(ref.Tag) > 0 { buf.WriteByte(':') buf.WriteString(ref.Tag) } return buf.String() } // pathAbsPair is the pair of a path (in a zip archive) and the absolute // filepath on disk of the file that will be placed at that path. type pathAbsPair struct { path string abs string } // pathAbsPairIO implements [modzip.FileIO] for [pathAbsPair] paths. type pathAbsPairIO struct{} func (pathAbsPairIO) Path(p pathAbsPair) string { return filepath.ToSlash(p.path) } func (pathAbsPairIO) Lstat(p pathAbsPair) (fs.FileInfo, error) { return os.Lstat(p.abs) } func (pathAbsPairIO) Open(p pathAbsPair) (io.ReadCloser, error) { return os.Open(p.abs) } // publishRegistryResolverShim implements a wrapper around // modregistry.Resolver that records information about the module being // published. // // If dryRun is true, it does not actually write to the underlying // registry. // // If outDir is non-empty, it also writes the contents of the module to // that directory. // // If recordFiles is true, it records which files are present in the // module's zip file. type publishRegistryResolverShim struct { resolver *modconfig.Resolver dryRun bool recordFiles bool outDir string initDirOnce sync.Once initDirError error // mu protects the fields below it. mu sync.Mutex registryName string insecure bool repository string tag string manifestDigest digest.Digest files []string descriptors []ociregistry.Descriptor } // ResolveToRegistry implements [modregistry.RegistryResolver]. func (r *publishRegistryResolverShim) ResolveToRegistry(mpath, vers string) (modregistry.RegistryLocation, error) { // Make sure that we can acquire the underlying registry even // though we are not going to use it, so we're dry-running as // much as possible regLoc, err := r.resolver.ResolveToRegistry(mpath, vers) if err != nil { return modregistry.RegistryLocation{}, err } loc, ok := r.resolver.ResolveToLocation(mpath, vers) if !ok { panic("unreachable: ResolveToLocation failed when ResolveToRegistry succeeded") } r.mu.Lock() defer r.mu.Unlock() r.registryName = loc.Host r.insecure = loc.Insecure return modregistry.RegistryLocation{ Registry: &publishRegistryShim{ Funcs: &ociregistry.Funcs{ NewError: func(ctx context.Context, methodName, repo string) error { return fmt.Errorf("unexpected OCI method %q invoked when publishing module", methodName) }, }, resolver: r, registry: regLoc.Registry, }, Repository: loc.Repository, Tag: loc.Tag, }, nil } func (r *publishRegistryResolverShim) writeIndex() error { if r.outDir == "" { return nil } index := ocispec.Index{ Versioned: ocispecroot.Versioned{ SchemaVersion: 2, }, MediaType: "application/vnd.oci.image.index.v1+json", Manifests: r.descriptors, } data, err := json.MarshalIndent(index, "", "\t") if err != nil { return err } data = append(data, '\n') if err := os.WriteFile(filepath.Join(r.outDir, "index.json"), data, 0o666); err != nil { return err } return nil } func (r *publishRegistryResolverShim) setRepository(repo string) error { r.mu.Lock() defer r.mu.Unlock() if r.repository != "" && repo != r.repository { return fmt.Errorf("internal error: publish wrote to more than one OCI repository") } r.repository = repo return nil } func (r *publishRegistryResolverShim) setTag(tag string, dig digest.Digest) error { r.mu.Lock() defer r.mu.Unlock() if r.tag != "" && tag != r.tag { return fmt.Errorf("internal error: publish wrote to more than one OCI tag") } r.tag = tag r.manifestDigest = dig return nil } func (r *publishRegistryResolverShim) setFiles(files []string) { r.mu.Lock() defer r.mu.Unlock() r.files = files } func (r *publishRegistryResolverShim) addManifest(tag string, data []byte, mediaType string) { r.mu.Lock() defer r.mu.Unlock() r.descriptors = append(r.descriptors, ociregistry.Descriptor{ MediaType: mediaType, Size: int64(len(data)), Digest: digest.FromBytes(data), Annotations: map[string]string{ "org.opencontainers.image.ref.name": tag, }, }) } func (r *publishRegistryResolverShim) initDir() error { // Lazily create the directory and the oci-layout file // so we don't create anything if no operations take place // on the registry. r.initDirOnce.Do(func() { if r.outDir == "" { return } if err := os.Mkdir(r.outDir, 0o777); err != nil { r.initDirError = err return } // Create oci-layout file. // See https://github.com/opencontainers/image-spec/blob/8f3820ccf8f65db8744e626df17fe8a64462aece/image-layout.md#oci-layout-file r.initDirError = os.WriteFile(filepath.Join(r.outDir, "oci-layout"), []byte(` { "imageLayoutVersion": "1.0.0" } `[1:]), 0o666) }) return r.initDirError } // publishRegistryShim implements [ociregistry.Interface] by recording // what is written. It returns an error for methods not expected to be // invoked as part of the publishing process. type publishRegistryShim struct { *ociregistry.Funcs resolver *publishRegistryResolverShim // registry is the real underlying registry. It is only used if // resolver.dryRun is false. registry ociregistry.Interface } func filesFromZip(content0 io.Reader, size int64) ([]string, error) { // The modregistry code (our only caller) always invokes PushBlob // with a ReaderAt, so we can avoid copying all the data by type-asserting // to that. content, ok := content0.(io.ReaderAt) if !ok { return nil, fmt.Errorf("internal error: PushBlob invoked without ReaderAt") } z, err := zip.NewReader(content, size) if err != nil { return nil, err } files := make([]string, len(z.File)) for i, f := range z.File { files[i] = f.Name } return files, nil } func (r *publishRegistryShim) PushBlob(ctx context.Context, repoName string, desc ociregistry.Descriptor, content io.Reader) (ociregistry.Descriptor, error) { if err := r.resolver.setRepository(repoName); err != nil { return ociregistry.Descriptor{}, err } if r.resolver.recordFiles && desc.MediaType == "application/zip" { files, err := filesFromZip(content, desc.Size) if err != nil { return ociregistry.Descriptor{}, err } r.resolver.setFiles(files) } switch { case r.resolver.outDir != "": if err := r.resolver.initDir(); err != nil { return ociregistry.Descriptor{}, err } outFile := filepath.Join(r.resolver.outDir, "blobs", string(desc.Digest.Algorithm()), desc.Digest.Encoded()) if err := os.MkdirAll(filepath.Dir(outFile), 0o777); err != nil { return ociregistry.Descriptor{}, err } // TODO create as temp and atomically rename? f, err := os.Create(outFile) if err != nil { return ociregistry.Descriptor{}, err } defer f.Close() if _, err := io.Copy(f, content); err != nil { return ociregistry.Descriptor{}, fmt.Errorf("cannot copy blob to %q: %v", outFile, err) } if err := f.Close(); err != nil { return ociregistry.Descriptor{}, err } case r.resolver.dryRun: // Sanity check we can read the content. if _, err := io.Copy(io.Discard, content); err != nil { return ociregistry.Descriptor{}, fmt.Errorf("error reading blob: %v", err) } default: return r.registry.PushBlob(ctx, repoName, desc, content) } return desc, nil } func (r *publishRegistryShim) PushManifest(ctx context.Context, repoName string, tag string, data []byte, mediaType string) (ociregistry.Descriptor, error) { if err := r.resolver.setRepository(repoName); err != nil { return ociregistry.Descriptor{}, err } desc := ociregistry.Descriptor{ Digest: digest.FromBytes(data), Size: int64(len(data)), } if err := r.resolver.setTag(tag, desc.Digest); err != nil { return ociregistry.Descriptor{}, err } r.resolver.addManifest(tag, data, mediaType) switch { case r.resolver.outDir != "": // The OCI image layout does not distinguish between data blobs and // manifest blobs, unlike the OCI registry API, so use PushBlob // to create the blob. return r.PushBlob(ctx, repoName, desc, bytes.NewReader(data)) case r.resolver.dryRun: return desc, nil default: return r.registry.PushManifest(ctx, repoName, tag, data, mediaType) } } cue-lang-cue-db9cc73/cmd/cue/cmd/modregistry.go000066400000000000000000000054161474664451600214670ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "context" "errors" "fmt" "net" "net/http" "os" "os/signal" "syscall" "time" "cuelabs.dev/go/oci/ociregistry" "cuelabs.dev/go/oci/ociregistry/ocimem" "cuelabs.dev/go/oci/ociregistry/ociserver" "github.com/spf13/cobra" ) func newModRegistryCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ // This command is hidden, for now at least, // because it's not clear whether it should be // officially supported. Hidden: true, Use: "registry [listen-address]", Short: "start a local in-memory module registry", Long: ` This command starts an OCI-compliant server that stores all its contents in memory. It can serve as a scratch CUE modules registry for use in testing. For example, start a local registry with: cue mod registry localhost:8080 and point CUE_REGISTRY to it to publish a module version: CUE_REGISTRY=localhost:8080 cue mod publish v0.0.1 Note: this command might be removed or changed significantly in the future. `[1:], RunE: mkRunE(c, runModRegistry), Args: cobra.MaximumNArgs(1), } return cmd } func runModRegistry(cmd *Command, args []string) error { addr := "localhost:0" if len(args) > 0 { addr = args[0] } l, err := net.Listen("tcp", addr) if err != nil { return err } fmt.Printf("listening on %v\n", l.Addr()) r := ocimem.NewWithConfig(&ocimem.Config{ ImmutableTags: true, }) srv := http.Server{ Handler: ociserver.New(ociTagLoggerRegistry{r}, nil), } var serveErr error go func() { if err := srv.Serve(l); !errors.Is(err, http.ErrServerClosed) { serveErr = err } }() sigint := make(chan os.Signal, 1) signal.Notify(sigint, os.Interrupt, syscall.SIGTERM) <-sigint ctx, cancal := context.WithTimeout(context.Background(), 2*time.Second) defer cancal() if err := srv.Shutdown(ctx); err != nil { fmt.Printf("HTTP server Shutdown: %v\n", err) return err } return serveErr } type ociTagLoggerRegistry struct { ociregistry.Interface } func (r ociTagLoggerRegistry) PushManifest(ctx context.Context, repo string, tag string, contents []byte, mediaType string) (ociregistry.Descriptor, error) { fmt.Printf("tagged %v@%v\n", repo, tag) return r.Interface.PushManifest(ctx, repo, tag, contents, mediaType) } cue-lang-cue-db9cc73/cmd/cue/cmd/modrename.go000066400000000000000000000142451474664451600210660ustar00rootroot00000000000000// Copyright 2025 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "os" "path/filepath" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/format" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/load" "cuelang.org/go/cue/parser" "cuelang.org/go/internal/mod/semver" "cuelang.org/go/mod/module" "github.com/spf13/cobra" ) func newModRenameCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "rename ", Short: "rename the current module", Long: `Rename changes the name of the current module, updating import statements in source files as required. Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, runModRename), Args: cobra.ExactArgs(1), } return cmd } type modRenamer struct { oldModulePath string oldModuleMajor string oldModuleQualifier string newModulePath string newModuleMajor string newModuleQualifier string } func runModRename(cmd *Command, args []string) error { modFilePath, mf, _, err := readModuleFile() if err != nil { return nil } if mf.Module == args[0] { // Nothing to do return nil } var mr modRenamer mr.oldModulePath, mr.oldModuleMajor, err = splitModulePath(mf.Module) if err != nil { return err } mr.oldModuleQualifier = module.ParseImportPath(mr.oldModulePath).Qualifier mf.Module = args[0] mr.newModulePath, mr.newModuleMajor, err = splitModulePath(mf.Module) if err != nil { return err } mr.newModuleQualifier = module.ParseImportPath(mr.newModulePath).Qualifier // TODO if we're renaming to a module that we currently depend on, // perhaps we should detect that and give an error. newModFileData, err := mf.Format() if err != nil { return fmt.Errorf("invalid resulting module.cue file after edits: %v", err) } if err := os.WriteFile(modFilePath, newModFileData, 0o666); err != nil { return err } modRoot, err := findModuleRoot() if err != nil { return err } binst := load.Instances([]string{"./..."}, &load.Config{ Dir: modRoot, ModuleRoot: modRoot, Tests: true, Tools: true, AllCUEFiles: true, Package: "*", // Note: the mod renaming can work even when // some external imports don't. SkipImports: true, }) if len(binst) == 0 { // No packages to rename. return nil } if binst[0].Module == "" { return fmt.Errorf("no current module to rename") } for _, inst := range binst { if err := inst.Err; err != nil { return err } for _, file := range inst.BuildFiles { if filepath.Dir(file.Filename) != inst.Dir { // Avoid processing files which are inherited from parent directories. continue } if err := mr.renameFile(file); err != nil { return err } } } return nil } func (mr *modRenamer) renameFile(file *build.File) error { syntax, err := parser.ParseFile(file.Filename, file.Source, parser.ParseComments) if err != nil { return err } changed := false for _, decl := range syntax.Preamble() { if decl, ok := decl.(*ast.ImportDecl); ok { for _, spec := range decl.Specs { ch, err := mr.rewriteImport(spec) if err != nil { return err } changed = changed || ch } } } if !changed { return nil } data, err := format.Node(syntax) if err != nil { return err } if err := os.WriteFile(file.Filename, data, 0o666); err != nil { return err } return nil } func (mr *modRenamer) rewriteImport(spec *ast.ImportSpec) (changed bool, err error) { importPath, err := literal.Unquote(spec.Path.Value) if err != nil { return false, fmt.Errorf("malformed import path in AST: %v", err) } ip := module.ParseImportPath(importPath) if !pkgIsUnderneath(ip.Path, mr.oldModulePath) { return false, nil } // TODO it's possible that we've got a import of a package in a nested module // rather than a reference to a package in this module. We can only // tell that by actually importing the dependencies and looking up the // package in those dependencies, which seems like overkill for now at least. if ip.Qualifier == "" { return false, fmt.Errorf("import path %q has no implied package qualifier", importPath) } if ip.Version != "" && ip.Version != mr.oldModuleMajor { // Same module, different major version. Don't change it. return false, nil } ip.Path = mr.newModulePath + strings.TrimPrefix(ip.Path, mr.oldModulePath) if ip.Version != "" { // Keep the major version if it was there already; the main // module is always the default. ip.Version = mr.newModuleMajor } // Note: ip.Qualifier remains the same as before, which means // that regardless of the new import path, the implied identifier // will remain the same, so no change is needed to spec.Ident. ip.ExplicitQualifier = false // Only include if needed. spec.Path.Value = literal.String.Quote(ip.String()) return true, nil } // pkgIsUnderneath reports whether pkg2 is a package // underneath (or the same as) pkg1. func pkgIsUnderneath(pkg1, pkg2 string) bool { if len(pkg1) < len(pkg2) { return false } if !strings.HasPrefix(pkg1, pkg2) { return false } return len(pkg1) == len(pkg2) || pkg1[len(pkg2)] == '/' } func splitModulePath(path string) (mpath string, mvers string, err error) { mpath, mvers, ok := module.SplitPathVersion(path) if ok { if semver.Major(mvers) != mvers { return "", "", fmt.Errorf("module path %q should contain the major version only", path) } if err := module.CheckPath(mpath); err != nil { return "", "", fmt.Errorf("invalid module path %q: %v", path, err) } return mpath, mvers, nil } mpath = path if err := module.CheckPathWithoutVersion(mpath); err != nil { return "", "", fmt.Errorf("invalid module path %q: %v", path, err) } return mpath, "v0", nil } cue-lang-cue-db9cc73/cmd/cue/cmd/modresolve.go000066400000000000000000000064021474664451600212720ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "strings" "cuelabs.dev/go/oci/ociregistry/ociref" "github.com/spf13/cobra" "cuelang.org/go/mod/modfile" "cuelang.org/go/mod/module" ) func newModResolveCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "resolve [[@] ...]", Short: "Show how a module path resolves to a registry", Long: `This command prints information about how a given module path will resolve to an actual registry in the form of an OCI reference. If the module version (which must be a canonical semver version) is omitted, it omits the tag from the reference. It only consults local information - it works lexically with respect to the registry configuration (see "cue help registryconfig") and does not make any network calls to check whether the module exists. If no arguments are provided, the current module path is used. This is equivalent to specifying "." as an argument, which also refers to the current module. Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, runModResolve), } return cmd } func runModResolve(cmd *Command, args []string) error { resolver, err := getRegistryResolver() if err != nil { return err } var mf *modfile.File if len(args) == 0 { // Use the current module if no arguments are provided. args = []string{"."} } for _, arg := range args { if arg == "." { if mf == nil { var err error _, mf, _, err = readModuleFile() if err != nil { return err } } arg = mf.Module } mpath, vers, ok := strings.Cut(arg, "@") if ok { if _, err := module.ParseVersion(arg); err != nil { return fmt.Errorf("invalid module path: %v", err) } } else { mpath = arg if err := module.CheckPathWithoutVersion(arg); err != nil { return fmt.Errorf("invalid module path: %v", err) } } loc, ok := resolver.ResolveToLocation(mpath, vers) if !ok { // TODO should we print this and carry on anyway? // And perhaps return a silent error when we do that? return fmt.Errorf("no registry found for module %q", arg) } ref := ociref.Reference{ Host: loc.Host, Repository: loc.Repository, } // TODO when vers is empty, loc.Tag does actually contain the // tag prefix (if any) so we could potentially provide more info, // but it might be misleading so leave it out for now. // Also, there's no way in the standard OCI reference syntax to // indicate that a connection is insecure, so leave out that // info too. We could use our own syntax (+insecure) but // that arguably makes the output less useful as it won't be // acceptable to standard tooling. if vers != "" { ref.Tag = loc.Tag } fmt.Println(ref) } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/modtidy.go000066400000000000000000000066041474664451600205700ustar00rootroot00000000000000// Copyright 2023 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bytes" "errors" "fmt" "os" "path/filepath" "github.com/spf13/cobra" "cuelang.org/go/internal/mod/modload" "cuelang.org/go/mod/modfile" ) func newModTidyCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "tidy", Short: "download and tidy module dependencies", Long: `Tidy resolves all module dependencies in the current module and updates the cue.mod/module.cue file to reflect them. It also removes dependencies that are not needed. It will attempt to fetch modules that aren't yet present in the dependencies by fetching the latest available version from a registry. See "cue help environment" for details on how $CUE_REGISTRY is used to determine the modules registry. Note that this command is not yet stable and may be changed. `, RunE: mkRunE(c, runModTidy), Args: cobra.ExactArgs(0), } cmd.Flags().Bool(string(flagCheck), false, "check for tidiness after fetching dependencies; fail if module.cue would be updated") return cmd } func runModTidy(cmd *Command, args []string) error { reg, err := getCachedRegistry() if err != nil { return err } ctx := backgroundContext() modRoot, err := findModuleRoot() if err != nil { return err } if flagCheck.Bool(cmd) { err := modload.CheckTidy(ctx, os.DirFS(modRoot), ".", reg) return suggestModCommand(err) } mf, err := modload.Tidy(ctx, os.DirFS(modRoot), ".", reg) if err != nil { return suggestModCommand(err) } data, err := mf.Format() if err != nil { return fmt.Errorf("internal error: invalid module.cue file generated: %v", err) } modPath := filepath.Join(modRoot, "cue.mod", "module.cue") oldData, err := os.ReadFile(modPath) if err != nil { // Shouldn't happen because modload.Load returns an error // if it can't load the module file. return err } if bytes.Equal(data, oldData) { return nil } if err := os.WriteFile(modPath, data, 0o666); err != nil { return err } return nil } // suggestModCommand rewrites a non-nil error to suggest to the user // what command they could use to fix a problem. // [modload.ErrModuleNotTidy] suggests running `cue mod tidy`, // and [modfile.ErrNoLanguageVersion] suggests running `cue mod fix`. func suggestModCommand(err error) error { notTidyErr := new(modload.ErrModuleNotTidy) switch { case errors.Is(err, modfile.ErrNoLanguageVersion): // TODO(mvdan): note that we cannot use standard Go error wrapping here via %w // as then errors.Print calls errors.Errors which reaches for the first CUE error // via errors.As, skipping over any non-CUE-wrapped errors. err = fmt.Errorf("%v; run 'cue mod fix'", err) case errors.As(err, ¬TidyErr): if notTidyErr.Reason == "" { err = fmt.Errorf("module is not tidy, use 'cue mod tidy'") } else { err = fmt.Errorf("module is not tidy, use 'cue mod tidy': %v", notTidyErr.Reason) } } return err } cue-lang-cue-db9cc73/cmd/cue/cmd/orphans.go000066400000000000000000000225751474664451600205760ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "path/filepath" "strconv" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/encoding/protobuf/jsonpb" "cuelang.org/go/internal" "cuelang.org/go/internal/astinternal" "cuelang.org/go/internal/encoding" ) // This file contains logic for placing orphan files within a CUE namespace. func (b *buildPlan) usePlacement() bool { return b.perFile || b.useList || len(b.path) > 0 } func (b *buildPlan) parsePlacementFlags() error { cmd := b.cmd // Flags which only exist for `cue import`. if b.importing { b.perFile = flagFiles.Bool(cmd) } b.useList = flagList.Bool(cmd) b.useContext = flagWithContext.Bool(cmd) for _, str := range flagPath.StringArray(cmd) { l, err := parser.ParseExpr("--path", str) if err != nil { labels, err := parseFullPath(str) if err != nil { return fmt.Errorf( `labels must be expressions (-l foo -l 'strings.ToLower(bar)') or full paths (-l '"foo": "\(strings.ToLower(bar))":) : %v`, err) } b.path = append(b.path, labels...) continue } b.path = append(b.path, &ast.ParenExpr{X: l}) } if !b.importing && !b.perFile && !b.useList && len(b.path) == 0 { if b.useContext { return fmt.Errorf( "flag %q must be used with at least one of flag %q, %q, or %q", flagWithContext, flagPath, flagList, flagFiles, ) } } else if b.schema != nil { return fmt.Errorf( "cannot combine --%s flag with flag %q, %q, or %q", flagSchema, flagPath, flagList, flagFiles, ) } return nil } func (b *buildPlan) placeOrphans(i *build.Instance, a []*decoderInfo) error { pkg := b.encConfig.PkgName if pkg == "" { pkg = i.PkgName } else if pkg != "" && i.PkgName != "" && i.PkgName != pkg && !flagForce.Bool(b.cmd) { return fmt.Errorf( "%q flag clashes with existing package name (%s vs %s)", flagPackage, pkg, i.PkgName, ) } var files []*ast.File for _, di := range a { if !i.User && !b.matchFile(filepath.Base(di.file.Filename)) { continue } d := di.dec(b) var objs []*ast.File // Filter only need to filter files that can stream: for ; !d.Done(); d.Next() { if f := d.File(); f != nil { f.Filename = newName(d.Filename(), 0) objs = append(objs, f) } } if err := d.Err(); err != nil { return err } d.Close() if b.perFile { for i, obj := range objs { f, err := placeOrphans(b, d, pkg, obj) if err != nil { return err } f.Filename = newName(d.Filename(), i) files = append(files, f) } continue } // TODO: consider getting rid of this requirement. It is important that // import will catch conflicts ahead of time then, though, and report // this messages as a possible solution if there are conflicts. if b.importing && len(objs) > 1 && len(b.path) == 0 && !b.useList { return fmt.Errorf( "%s, %s, or %s flag needed to handle multiple objects in file %s", flagPath, flagList, flagFiles, shortFile(i.Root, di.file)) } if !b.useList && len(b.path) == 0 && !b.useContext { for _, f := range objs { if pkg := b.encConfig.PkgName; pkg != "" { internal.SetPackage(f, pkg, false) } files = append(files, f) } } else { // TODO: handle imports correctly, i.e. for proto. f, err := placeOrphans(b, d, pkg, objs...) if err != nil { return err } f.Filename = newName(d.Filename(), 0) files = append(files, f) } } b.imported = append(b.imported, files...) for _, f := range files { if err := i.AddSyntax(f); err != nil { return err } } return nil } func placeOrphans(b *buildPlan, d *encoding.Decoder, pkg string, objs ...*ast.File) (*ast.File, error) { f := &ast.File{} filename := d.Filename() index := newIndex() for i, file := range objs { if i == 0 { astutil.CopyMeta(f, file) } expr := internal.ToExpr(file) var path cue.Path var labels []ast.Label switch { case len(b.path) > 0: expr := expr if b.useContext { expr = ast.NewStruct( "data", expr, "filename", ast.NewString(filename), "index", ast.NewLit(token.INT, strconv.Itoa(i)), "recordCount", ast.NewLit(token.INT, strconv.Itoa(len(objs))), ) } var f *ast.File if s, ok := expr.(*ast.StructLit); ok { f = &ast.File{Decls: s.Elts} } else { f = &ast.File{Decls: []ast.Decl{&ast.EmbedDecl{Expr: expr}}} } err := astutil.Sanitize(f) if err != nil { return nil, errors.Wrapf(err, token.NoPos, "invalid combination of input files") } ctx := b.cmd.ctx inst := ctx.BuildFile(f) if err := inst.Err(); err != nil { return nil, err } var a []cue.Selector for _, label := range b.path { switch x := label.(type) { case *ast.Ident, *ast.BasicLit: case ast.Expr: if p, ok := x.(*ast.ParenExpr); ok { x = p.X // unwrap for better error messages } l := ctx.BuildExpr(x, cue.InferBuiltins(true), cue.Scope(inst)) switch l.Kind() { case cue.StringKind, cue.IntKind: label = l.Syntax().(ast.Label) default: var arg interface{} = l if err := l.Err(); err != nil { arg = err } return nil, fmt.Errorf( `error evaluating label %v: %v`, astinternal.DebugStr(x), arg) } } ast.SetPos(label, token.NoPos) a = append(a, cue.Label(label)) labels = append(labels, label) } path = cue.MakePath(a...) } switch d.Interpretation() { case build.ProtobufJSON: v := b.instance.Value().LookupPath(path) if b.useList { v, _ = v.Elem() } if !v.Exists() { break } if err := jsonpb.NewDecoder(v).RewriteFile(file); err != nil { return nil, err } } if b.useList { idx := index for _, e := range labels { idx = idx.label(e) } if idx.field.Value == nil { idx.field.Value = &ast.ListLit{ Lbrack: token.NoSpace.Pos(), Rbrack: token.NoSpace.Pos(), } } list := idx.field.Value.(*ast.ListLit) list.Elts = append(list.Elts, expr) } else if len(labels) == 0 { obj, ok := expr.(*ast.StructLit) if !ok { if _, ok := expr.(*ast.ListLit); ok { return nil, fmt.Errorf("expected struct as object root, did you mean to use the --list flag?") } return nil, fmt.Errorf("cannot map non-struct to object root") } f.Decls = append(f.Decls, obj.Elts...) } else { field := &ast.Field{Label: labels[0]} f.Decls = append(f.Decls, field) if pkg := internal.Package(file); pkg != nil { astutil.CopyComments(field, pkg) } for _, e := range labels[1:] { newField := &ast.Field{Label: e} newVal := ast.NewStruct(newField) field.Value = newVal field = newField } field.Value = expr } } if pkg != "" { internal.SetPackage(f, pkg, false) } if b.useList { switch x := index.field.Value.(type) { case *ast.StructLit: f.Decls = append(f.Decls, x.Elts...) case *ast.ListLit: f.Decls = append(f.Decls, &ast.EmbedDecl{Expr: x}) case nil: f.Decls = append(f.Decls, ast.NewList()) default: panic(fmt.Sprintf("unexpected type %T", x)) } } return f, astutil.Sanitize(f) } func parseFullPath(exprs string) (p []ast.Label, err error) { f, err := parser.ParseFile("--path", exprs+"_") if err != nil { return p, fmt.Errorf("parser error in path %q: %v", exprs, err) } if len(f.Decls) != 1 { return p, errors.New("path flag must be a space-separated sequence of labels") } for d := f.Decls[0]; ; { field, ok := d.(*ast.Field) if !ok { // This should never happen return p, errors.New("%q not a sequence of labels") } switch x := field.Label.(type) { case *ast.Ident, *ast.BasicLit: p = append(p, x) case ast.Expr: p = append(p, &ast.ParenExpr{X: x}) default: return p, fmt.Errorf("unsupported label type %T", x) } v, ok := field.Value.(*ast.StructLit) if !ok { break } if len(v.Elts) != 1 { return p, errors.New("path value may not contain a struct") } d = v.Elts[0] } return p, nil } type listIndex struct { index map[string]*listIndex field *ast.Field } func newIndex() *listIndex { return &listIndex{ index: map[string]*listIndex{}, field: &ast.Field{}, } } func (x *listIndex) label(label ast.Label) *listIndex { key := astinternal.DebugStr(label) idx := x.index[key] if idx == nil { if x.field.Value == nil { x.field.Value = &ast.StructLit{} } obj := x.field.Value.(*ast.StructLit) newField := &ast.Field{Label: label} obj.Elts = append(obj.Elts, newField) idx = &listIndex{ index: map[string]*listIndex{}, field: newField, } x.index[key] = idx } return idx } func newName(filename string, i int) string { if filename == "-" { return filename } ext := filepath.Ext(filename) filename = filename[:len(filename)-len(ext)] if i > 0 { filename += fmt.Sprintf("-%d", i) } filename += ".cue" return filename } cue-lang-cue-db9cc73/cmd/cue/cmd/registry.go000066400000000000000000000020721474664451600207620ustar00rootroot00000000000000package cmd import ( "log/slog" "net/http" "os" "cuelang.org/go/internal/cuedebug" "cuelang.org/go/internal/httplog" "cuelang.org/go/internal/mod/modload" "cuelang.org/go/mod/modconfig" ) // getRegistryResolver returns an implementation of [modregistry.Resolver] // that resolves to registries as specified in the configuration. func getRegistryResolver() (*modconfig.Resolver, error) { return modconfig.NewResolver(newModConfig()) } func getCachedRegistry() (modload.Registry, error) { return modconfig.NewRegistry(newModConfig()) } func newModConfig() *modconfig.Config { return &modconfig.Config{ Transport: httpTransport(), ClientType: "cmd/cue", } } func httpTransport() http.RoundTripper { if !cuedebug.Flags.HTTP { return http.DefaultTransport } return httplog.Transport(&httplog.TransportConfig{ // It would be nice to use the default slog logger, // but that does a terrible job of printing structured // values, so use JSON output instead. Logger: httplog.SlogLogger{ Logger: slog.New(slog.NewJSONHandler(os.Stderr, nil)), }, }) } cue-lang-cue-db9cc73/cmd/cue/cmd/root.go000066400000000000000000000242311474664451600200760ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "context" "encoding/json" "fmt" "io" "os" "runtime" "runtime/pprof" "testing" "github.com/spf13/cobra" "golang.org/x/text/message" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/interpreter/embed" "cuelang.org/go/cue/stats" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/cueexperiment" "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" ) // TODO: commands // fix: rewrite/refactor configuration files // -i interactive: open diff and ask to update // serve: like cmd, but for servers // get: convert cue from other languages, like proto and go. // gen: generate files for other languages // generate like go generate (also convert cue to go doc) // test load and fully evaluate test files. // // TODO: documentation of concepts // tasks the key element for cmd, serve, and fix type runFunction func(cmd *Command, args []string) error // wasmInterp is set when the cuewasm build tag is enbabled. var wasmInterp cuecontext.ExternInterpreter func statsEncoder(cmd *Command) (*encoding.Encoder, error) { file := os.Getenv("CUE_STATS_FILE") if file == "" { return nil, nil } stats, err := filetypes.ParseFile(file, filetypes.Export) if err != nil { return nil, err } return encoding.NewEncoder(cmd.ctx, stats, &encoding.Config{ Stdout: cmd.OutOrStderr(), Force: true, }) } // Stats expands [stats.Counts] with counters obtained from other sources, // such as the Go runtime. The stats are grouped by category to clarify their source. type Stats struct { // CUE groups stats obtained from the CUE evaluator. CUE stats.Counts // Go groups stats obtained from the Go runtime. Go struct { AllocBytes uint64 AllocObjects uint64 } } func mkRunE(c *Command, f runFunction) func(*cobra.Command, []string) error { return func(cmd *cobra.Command, args []string) error { c.Command = cmd // Note that the setup code below should only run once per cmd/cue invocation. // This is because part of it modifies the global state like cueexperiment, // but also because running this twice may result in broken CUE stats or Go profiles. // However, users of the exposed Go API may be creating and running many commands, // so we can't panic or fail if this setup work happens twice. statsEnc, err := statsEncoder(c) if err != nil { return err } if err := cueexperiment.Init(); err != nil { return err } var opts []cuecontext.Option if wasmInterp != nil { opts = append(opts, cuecontext.Interpreter(wasmInterp)) } // CUE_EXPERIMENT=embed should probably be obeyed by [cuecontext.New] just like // other flags such as evalv3 or toposort. Currently that causes an import cycle. // See: https://cuelang.org/issue/3613 if cueexperiment.Flags.Embed { opts = append(opts, cuecontext.Interpreter(embed.New())) } c.ctx = cuecontext.New(opts...) // Some init work, such as in internal/filetypes, evaluates CUE by design. // We don't want that work to count towards $CUE_STATS. adt.ResetStats() if cpuprofile := flagCpuProfile.String(c); cpuprofile != "" { f, err := os.Create(cpuprofile) if err != nil { return fmt.Errorf("could not create CPU profile: %v", err) } defer f.Close() if err := pprof.StartCPUProfile(f); err != nil { return fmt.Errorf("could not start CPU profile: %v", err) } defer pprof.StopCPUProfile() } err = f(c, args) // TODO(mvdan): support -memprofilerate like `go help testflag`. if memprofile := flagMemProfile.String(c); memprofile != "" { f, err := os.Create(memprofile) if err != nil { return fmt.Errorf("could not create memory profile: %v", err) } defer f.Close() runtime.GC() // get up-to-date statistics if err := pprof.WriteHeapProfile(f); err != nil { return fmt.Errorf("could not write memory profile: %v", err) } } if statsEnc != nil { var stats Stats stats.CUE = adt.TotalStats() // Fill in the runtime stats, which are cumulative counters. // Since in practice the number of allocations isn't fully deterministic, // due to the inherent behavior of memory pools like sync.Pool, // we support supplying MemStats as a JSON file in the tests. var m runtime.MemStats if name := os.Getenv("CUE_TEST_MEMSTATS"); name != "" && testing.Testing() { bs, err := os.ReadFile(name) if err != nil { return err } if err := json.Unmarshal(bs, &m); err != nil { return err } } else { runtime.ReadMemStats(&m) } stats.Go.AllocBytes = m.TotalAlloc stats.Go.AllocObjects = m.Mallocs statsEnc.Encode(c.ctx.Encode(stats)) statsEnc.Close() } return err } } // TODO(mvdan): remove this error return at some point. // The API could also be made clearer if we want to keep cmd public, // such as not leaking *cobra.Command via embedding. // New creates the top-level command. // The returned error is always nil, and is a historical artifact. func New(args []string) (*Command, error) { cmd := &cobra.Command{ Use: "cue", // TODO: the short help text below seems to refer to `cue cmd`, like helpTemplate. Short: "cue emits configuration files to user-defined commands.", // We print errors ourselves in Main, which allows for ErrPrintedError. // Similarly, we don't want to print the entire help text on any error. // We can explicitly trigger help on certain errors via pflag.ErrHelp. SilenceErrors: true, SilenceUsage: true, } c := &Command{ Command: cmd, root: cmd, } c.cmdCmd = newCmdCmd(c) addGlobalFlags(cmd.PersistentFlags()) // Cobra's --help flag shows up in help text by default, which is unnecessary. cmd.InitDefaultHelpFlag() cmd.Flag("help").Hidden = true // "help" is treated as a special command by cobra. // We use our own template to be more in control of the structure of `cue help`. // Note that we need to add helpCmd as a subcommand first, for cobra to work out // the proper help text paddings for additional help topics. helpCmd := newHelpCmd(c) cmd.AddCommand(helpCmd) for _, sub := range helpTopics { helpCmd.AddCommand(sub) } cmd.SetHelpCommand(helpCmd) cmd.SetHelpTemplate(helpTemplate) for _, sub := range []*cobra.Command{ c.cmdCmd, newCompletionCmd(c), newEvalCmd(c), newDefCmd(c), newExportCmd(c), newFixCmd(c), newFmtCmd(c), newGetCmd(c), newImportCmd(c), newLoginCmd(c), newModCmd(c), newTrimCmd(c), newVersionCmd(c), newVetCmd(c), // Hidden newExpCmd(c), newAddCmd(c), newLSPCmd(c), } { cmd.AddCommand(sub) } cmd.SetArgs(args) return c, nil } // rootWorkingDir avoids repeated calls to [os.Getwd] in cmd/cue. // If we can't figure out the current directory, something is very wrong, // and there's no point in continuing to run a command. var rootWorkingDir = func() string { wd, err := os.Getwd() if err != nil { fmt.Fprintf(os.Stderr, "cannot get current directory: %v\n", err) os.Exit(1) } return wd }() // Main runs the cue tool and returns the code for passing to os.Exit. func Main() int { cmd, _ := New(os.Args[1:]) if err := cmd.Run(backgroundContext()); err != nil { if err != ErrPrintedError { errors.Print(os.Stderr, err, &errors.Config{ Cwd: rootWorkingDir, ToSlash: testing.Testing(), }) } return 1 } return 0 } type Command struct { // The currently active command. *cobra.Command root *cobra.Command // _tool.cue subcommands. cmdCmd *cobra.Command ctx *cue.Context hasErr bool } type errWriter Command func (w *errWriter) Write(b []byte) (int, error) { c := (*Command)(w) c.hasErr = len(b) > 0 return c.Command.OutOrStderr().Write(b) } // Hint: search for uses of OutOrStderr other than the one here to see // which output does not trigger a non-zero exit code. os.Stderr may never // be used directly. // Stderr returns a writer that should be used for error messages. // Writing to it will result in the command's exit code being 1. // // TODO(mvdan): provide an alternative to write to stderr without setting the exit code to 1. func (c *Command) Stderr() io.Writer { return (*errWriter)(c) } // TODO: add something similar for Stdout. The output model of Cobra isn't // entirely clear, and such a change seems non-trivial. // Consider overriding these methods from Cobra using OutOrStdErr. // We don't use them currently, but may be safer to block. Having them // will encourage their usage, and the naming is inconsistent with other CUE APIs. // PrintErrf(format string, args ...interface{}) // PrintErrln(args ...interface{}) // PrintErr(args ...interface{}) func (c *Command) SetOutput(w io.Writer) { c.root.SetOut(w) } func (c *Command) SetInput(r io.Reader) { c.root.SetIn(r) } // ErrPrintedError indicates error messages have been printed directly to stderr, // and can be used so that the returned error itself isn't printed as well. var ErrPrintedError = errors.New("terminating because of errors") // printError uses cue/errors to print an error to stderr when non-nil. func printError(cmd *Command, err error) { if err == nil { return } // Link x/text as our localizer. p := message.NewPrinter(getLang()) format := func(w io.Writer, format string, args ...interface{}) { p.Fprintf(w, format, args...) } errors.Print(cmd.Stderr(), err, &errors.Config{ Format: format, Cwd: rootWorkingDir, ToSlash: testing.Testing(), }) } func (c *Command) Run(ctx context.Context) (err error) { // Three categories of commands: // - normal // - user defined // - help // For the latter two, we need to use the default loading. if err := c.root.Execute(); err != nil { return err } if c.hasErr { return ErrPrintedError } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/root_cuewasm.go000066400000000000000000000015621474664451600216240ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build cuewasm package cmd import ( "cuelang.org/go/cue/interpreter/wasm" ) func init() { // The wasm interpreter can be enabled by default once we are ready to ship the feature. // For now, it's not ready, and makes cue binaries heavier by over 2MiB. wasmInterp = wasm.New() } cue-lang-cue-db9cc73/cmd/cue/cmd/root_test.go000066400000000000000000000035221474664451600211350ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd_test import ( "bytes" "context" "io" "strings" "testing" "cuelang.org/go/cmd/cue/cmd" "github.com/go-quicktest/qt" ) // The cmd package exposes some APIs, which some users rely on. // Ensure that they continue to work as advertised. func TestCommand(t *testing.T) { ctx := context.Background() // Create one command and run it, only checking that it succeeds. c, err := cmd.New([]string{"help", "export"}) qt.Assert(t, qt.IsNil(err)) c.SetOutput(io.Discard) err = c.Run(ctx) qt.Assert(t, qt.IsNil(err)) // Create another command and run it, expecting it to fail. c, err = cmd.New([]string{"help", "nosuchcommand"}) qt.Assert(t, qt.IsNil(err)) c.SetOutput(io.Discard) err = c.Run(ctx) qt.Assert(t, qt.IsNotNil(err)) // Verify that SetInput and SetOutput work. c, err = cmd.New([]string{"export", "-"}) qt.Assert(t, qt.IsNil(err)) c.SetInput(strings.NewReader("foo: 123\n")) var buf bytes.Buffer c.SetOutput(&buf) err = c.Run(ctx) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.Equals(buf.String(), "{\n \"foo\": 123\n}\n")) // Verify that we can use the API exposed by the embedded cobra command. c, err = cmd.New([]string{"fmt", "nosuchfile.cue"}) qt.Assert(t, qt.IsNil(err)) err = c.Execute() qt.Assert(t, qt.IsNotNil(err)) } cue-lang-cue-db9cc73/cmd/cue/cmd/script_test.go000066400000000000000000000437021474664451600214620ustar00rootroot00000000000000// Copyright 2020 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "bufio" "bytes" "context" "encoding/json" "fmt" "io" "io/fs" "net/http" "net/http/httptest" "net/url" "os" "path" "path/filepath" "strconv" "strings" "sync/atomic" "testing" "time" "cuelabs.dev/go/oci/ociregistry/ociclient" "cuelabs.dev/go/oci/ociregistry/ocimem" "cuelabs.dev/go/oci/ociregistry/ociref" "cuelabs.dev/go/oci/ociregistry/ociserver" "github.com/google/shlex" "github.com/rogpeppe/go-internal/goproxytest" "github.com/rogpeppe/go-internal/gotooltest" "github.com/rogpeppe/go-internal/testscript" "golang.org/x/oauth2" "golang.org/x/tools/txtar" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/parser" "cuelang.org/go/internal/cuetest" "cuelang.org/go/internal/cueversion" "cuelang.org/go/internal/mod/semver" "cuelang.org/go/internal/registrytest" ) // TestLatest checks that the examples match the latest language standard, // even if still valid in backwards compatibility mode. func TestLatest(t *testing.T) { root := filepath.Join("testdata", "script") if err := filepath.WalkDir(root, func(fullpath string, entry fs.DirEntry, err error) error { if err != nil { return err } if !strings.HasSuffix(fullpath, ".txtar") || strings.HasPrefix(filepath.Base(fullpath), "fix") { return nil } a, err := txtar.ParseFile(fullpath) if err != nil { return err } if bytes.HasPrefix(a.Comment, []byte("!")) { return nil } for _, f := range a.Files { t.Run(path.Join(fullpath, f.Name), func(t *testing.T) { if !strings.HasSuffix(f.Name, ".cue") || path.Base(f.Name) == "invalid.cue" { return } v := parser.FromVersion(parser.Latest) _, err := parser.ParseFile(f.Name, f.Data, v) if err != nil { w := &bytes.Buffer{} fmt.Fprintf(w, "\n%s:\n", fullpath) errors.Print(w, err, nil) t.Error(w.String()) } }) } return nil }); err != nil { t.Fatal(err) } } func TestScript(t *testing.T) { srv := goproxytest.NewTestServer(t, filepath.Join("testdata", "mod"), "") p := testscript.Params{ Dir: filepath.Join("testdata", "script"), UpdateScripts: cuetest.UpdateGoldenFiles, RequireExplicitExec: true, RequireUniqueNames: true, Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){ // env-fill rewrites its argument files to replace any environment variable // references with their values, using the same algorithm as cmpenv. "env-fill": func(ts *testscript.TestScript, neg bool, args []string) { if neg || len(args) == 0 { ts.Fatalf("usage: env-fill args...") } for _, arg := range args { path := ts.MkAbs(arg) data := ts.ReadFile(path) data = tsExpand(ts, data) ts.Check(os.WriteFile(path, []byte(data), 0o666)) } }, // mod-time prints the modification time of a file to stdout. // The time is displayed as nanoseconds since the Unix epoch. "mod-time": func(ts *testscript.TestScript, neg bool, args []string) { if neg || len(args) != 1 { ts.Fatalf("usage: mod-time PATH") } path := ts.MkAbs(args[0]) fi, err := os.Stat(path) ts.Check(err) _, err = fmt.Fprint(ts.Stdout(), fi.ModTime().UnixNano()) ts.Check(err) }, // get-manifest writes the manifest for a given reference within an OCI // registry to a file in JSON format. "get-manifest": func(ts *testscript.TestScript, neg bool, args []string) { usage := func() { ts.Fatalf("usage: get-metadata OCI-ref@tag dest-file") } if neg { usage() } if len(args) != 2 { usage() } ref, err := ociref.Parse(args[0]) if err != nil { ts.Fatalf("invalid OCI reference %q: %v", args[0], err) } if ref.Tag == "" { ts.Fatalf("no tag in OCI reference %q", args[0]) } client, err := ociclient.New(ref.Host, &ociclient.Options{ Insecure: true, }) ts.Check(err) r, err := client.GetTag(context.Background(), ref.Repository, ref.Tag) ts.Check(err) data, err := io.ReadAll(r) ts.Check(err) err = os.WriteFile(ts.MkAbs(args[1]), data, 0o666) ts.Check(err) }, // memregistry starts an in-memory OCI server and sets the argument // environment variable name to its hostname. "memregistry": func(ts *testscript.TestScript, neg bool, args []string) { usage := func() { ts.Fatalf("usage: memregistry [-auth=username:password] ") } if neg { usage() } var auth *registrytest.AuthConfig if len(args) > 0 && strings.HasPrefix(args[0], "-") { userPass, ok := strings.CutPrefix(args[0], "-auth=") if !ok { usage() } user, pass, ok := strings.Cut(userPass, ":") if !ok { usage() } auth = ®istrytest.AuthConfig{ Username: user, Password: pass, } args = args[1:] } if len(args) != 1 { usage() } srv, err := registrytest.NewServer(ocimem.NewWithConfig(&ocimem.Config{ImmutableTags: true}), auth) if err != nil { ts.Fatalf("cannot start registrytest server: %v", err) } ts.Setenv(args[0], srv.Host()) ts.Defer(srv.Close) }, // memregistry starts an HTTP server with enough endpoints to test `cue login`. // It takes a single argument to describe the oauth server's behavior: // // * device-code-expired: polling for a token with device_code // always responds with [tokenErrorCodeExpired] // * pending-success: polling for a token with device_code // responds with [tokenErrorCodePending] once, and then succeeds // * immediate-success: polling for a token with device_code succeeds right away "oauthregistry": func(ts *testscript.TestScript, neg bool, args []string) { if neg || len(args) != 1 { ts.Fatalf("usage: oauthregistry ") } srv := newMockRegistryOauth(args[0]) u, _ := url.Parse(srv.URL) ts.Setenv("CUE_REGISTRY", u.Host+"+insecure") ts.Defer(srv.Close) }, // find-files recursively lists files under a directory, like `find -type f` on Linux. // It prints slash-separated paths relative to the root working directory of the testscript run, // for the sake of avoiding verbose and non-deterministic absolute paths. "find-files": func(ts *testscript.TestScript, neg bool, args []string) { if neg || len(args) == 0 { ts.Fatalf("usage: find-files args...") } out := ts.Stdout() workdir := ts.Getenv("WORK") for _, arg := range args { path := ts.MkAbs(arg) err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.Type().IsRegular() { rel, err := filepath.Rel(workdir, path) ts.Check(err) fmt.Fprintln(out, filepath.ToSlash(rel)) } return nil }) ts.Check(err) } }, }, Setup: func(e *testscript.Env) error { // If a testscript loads CUE packages but forgot to set up a cue.mod, // we might walk up to the system's temporary directory looking for cue.mod. // If /tmp/cue.mod exists for instance, this can lead to test failures // as our behavior when it comes to the module root and file paths changes. // Make the testscript.Params.WorkdirRoot directory a module, // ensuring consistent behavior no matter what parent directories contain. // // Note that creating the directory is enough for now, // and we ignore ErrExist since only the first test will succeed. // We can't create the directory before testscript.Run, as it sets up WorkdirRoot. workdirRoot := filepath.Dir(e.WorkDir) if err := os.Mkdir(filepath.Join(workdirRoot, "cue.mod"), 0o777); err != nil && !errors.Is(err, fs.ErrExist) { return err } e.Vars = append(e.Vars, "GOPROXY="+srv.URL, "GONOSUMDB=*", // GOPROXY is a private proxy // The current language version which would be added by `cue mod init`, e.g. v0.10.0. "CUE_LANGUAGE_VERSION="+cueversion.LanguageVersion(), // A later language version which only increases the bugfix release, e.g. v0.10.99. "CUE_LANGUAGE_VERSION_BUGFIX="+semver.MajorMinor(cueversion.LanguageVersion())+".99", ) entries, err := os.ReadDir(e.WorkDir) if err != nil { return fmt.Errorf("cannot read workdir: %v", err) } // Since os.UserCacheDir relies on OS-specific env vars that we don't set, // explicitly set up the cache directory somewhere predictable. e.Vars = append(e.Vars, "CUE_CACHE_DIR="+filepath.Join(e.WorkDir, ".tmp/cache")) for _, entry := range entries { if !entry.IsDir() { continue } regID, ok := strings.CutPrefix(entry.Name(), "_registry") if !ok { continue } // There's a _registry directory. Start a fake registry server to serve // the modules in it. registryDir := filepath.Join(e.WorkDir, entry.Name()) prefix := "" if data, err := os.ReadFile(filepath.Join(e.WorkDir, "_registry"+regID+"_prefix")); err == nil { prefix = strings.TrimSpace(string(data)) } useProxy := false proxyFile := filepath.Join(e.WorkDir, "_registry"+regID+"_proxy") if data, err := os.ReadFile(proxyFile); err == nil { useProxy, err = strconv.ParseBool(strings.TrimSpace(string(data))) if err != nil { return fmt.Errorf("invalid contents of proxy file %q: %v", proxyFile, err) } } reg, err := registrytest.New(os.DirFS(registryDir), prefix) if err != nil { return fmt.Errorf("cannot start test registry server: %v", err) } e.Defer(reg.Close) if prefix != "" { prefix = "/" + prefix } regHost := reg.Host() if useProxy { // Use a proxy for the registry, mirroring the way that the Central Registry // works. proxyClient, err := ociclient.New(regHost, &ociclient.Options{ Insecure: true, }) if err != nil { return fmt.Errorf("cannot create oci proxy client") } reg2 := httptest.NewServer(ociserver.New(proxyClient, nil)) reg2URL, _ := url.Parse(reg2.URL) regHost = reg2URL.Host e.Defer(reg2.Close) } e.Vars = append(e.Vars, "CUE_REGISTRY"+regID+"="+regHost+prefix+"+insecure", // This enables some tests to construct their own malformed // CUE_REGISTRY values that still refer to the test registry. "DEBUG_REGISTRY"+regID+"_HOST="+regHost, ) } return nil }, Condition: cuetest.Condition, } if err := gotooltest.Setup(&p); err != nil { t.Fatal(err) } testscript.Run(t, p) } // TestScriptDebug takes a single testscript file and then runs it within the // same process so it can be used for debugging. It runs the first cue command // it finds. // // Usage Comment out t.Skip() and set file to test. func TestX(t *testing.T) { t.Skip() const path = "./testdata/script/eval_e.txtar" check := func(err error) { t.Helper() if err != nil { t.Fatal(err) } } tmpdir := t.TempDir() a, err := txtar.ParseFile(filepath.FromSlash(path)) check(err) for _, f := range a.Files { name := filepath.Join(tmpdir, f.Name) check(os.MkdirAll(filepath.Dir(name), 0777)) check(os.WriteFile(name, f.Data, 0666)) } cwd, err := os.Getwd() check(err) defer func() { _ = os.Chdir(cwd) }() _ = os.Chdir(tmpdir) for s := bufio.NewScanner(bytes.NewReader(a.Comment)); s.Scan(); { cmd := s.Text() cmd = strings.TrimLeft(cmd, "! ") cmd = strings.TrimPrefix(cmd, "exec ") if !strings.HasPrefix(cmd, "cue ") { continue } args, err := shlex.Split(cmd) check(err) c, _ := New(args[1:]) b := &bytes.Buffer{} c.SetOutput(b) err = c.Run(context.Background()) // Always create an error to show t.Error(err, "\n", b.String()) return } t.Fatal("NO COMMAND FOUND") } func TestMain(m *testing.M) { check := func(err error) { if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } testscript.Main(m, map[string]func(){ "cue": func() { os.Exit(Main()) }, // Until https://github.com/rogpeppe/go-internal/issues/93 is fixed, // or we have some other way to use "exec" without caring about success, // this is an easy way for us to mimic `? exec cue`. "cue_exitzero": func() { Main() }, "cue_stdinpipe": func() { cwd, _ := os.Getwd() if err := mainStdinPipe(); err != nil { if err != ErrPrintedError { // print errors like Main errors.Print(os.Stderr, err, &errors.Config{ Cwd: cwd, ToSlash: testing.Testing(), }) } os.Exit(1) } }, "testcmd": func() { check(testCmd()) }, // Like `cue export`, but as a standalone Go program which doesn't // go through cmd/cue's setup of cuecontext and the evaluator. // Useful to check what the export behavior is for Go API users, // for example in relation to env vars like CUE_EXPERIMENT or CUE_DEBUG. // Only works with cue stdin and json stdout for simplicity. "cuectx_export": func() { input, err := io.ReadAll(os.Stdin) check(err) ctx := cuecontext.New() v := ctx.CompileBytes(input) err = v.Validate(cue.Concrete(true)) check(err) enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") err = enc.Encode(v) check(err) }, }) } func tsExpand(ts *testscript.TestScript, s string) string { return os.Expand(s, func(key string) string { return ts.Getenv(key) }) } func mainStdinPipe() error { // Like Main, but sets stdin to a pipe, // to emulate stdin reads like a terminal. cmd, _ := New(os.Args[1:]) pr, pw, err := os.Pipe() if err != nil { return err } cmd.SetInput(pr) _ = pw // we don't write to stdin at all, for now return cmd.Run(context.Background()) } func testCmd() error { cmd := os.Args[1] args := os.Args[2:] switch cmd { case "concurrent": // Used to test that we support running tasks concurrently. // Run like `concurrent foo bar` and `concurrent bar foo`, // each command creates one file and waits for the other to exist. // If the commands are run sequentially, neither will succeed. if len(args) != 2 { return fmt.Errorf("usage: concurrent to_create to_wait\n") } toCreate := args[0] toWait := args[1] if err := os.WriteFile(toCreate, []byte("dummy"), 0o666); err != nil { return err } for i := 0; i < 10; i++ { if _, err := os.Stat(toWait); err == nil { fmt.Printf("wrote %s and found %s\n", toCreate, toWait) return nil } time.Sleep(100 * time.Millisecond) } return fmt.Errorf("timed out waiting for %s to exist", toWait) default: return fmt.Errorf("unknown command: %q\n", cmd) } } // newMockRegistryOauth starts a test HTTP server with the OAuth2 device flow endpoints // used by `cue login` to obtain an access token. // Note that this HTTP server isn't an OCI registry yet, as that isn't needed for now. // // TODO: once we support refresh tokens, add those endpoints and test them too. func newMockRegistryOauth(mode string) *httptest.Server { mux := http.NewServeMux() ts := httptest.NewServer(mux) const ( staticUserCode = "user-code" staticDeviceCode = "device-code-longer-string" staticAccessToken = "secret-access-token" intervalSecs = 1 // 1s to keep the tests fast ) // OAuth2 Device Authorization Request endpoint: https://datatracker.ietf.org/doc/html/rfc8628#section-3.1 mux.HandleFunc("/login/device/code", func(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, oauth2.DeviceAuthResponse{ DeviceCode: staticDeviceCode, UserCode: staticUserCode, VerificationURI: ts.URL + "/login/device", VerificationURIComplete: ts.URL + "/login/device?user_code=" + url.QueryEscape(staticUserCode), Expiry: time.Now().Add(time.Minute), Interval: intervalSecs, }) }) // OAuth2 Token endpoint: https://datatracker.ietf.org/doc/html/rfc6749#section-3.2 var tokenRequestCounter atomic.Int64 mux.HandleFunc("/login/oauth/token", func(w http.ResponseWriter, r *http.Request) { deviceCode := r.FormValue("device_code") if deviceCode != staticDeviceCode { writeJSON(w, http.StatusBadRequest, tokenError{ErrorCode: tokenErrorCodeDenied}) return } switch mode { case "device-code-expired": writeJSON(w, http.StatusBadRequest, tokenError{ErrorCode: tokenErrorCodeExpired}) case "pending-success": count := tokenRequestCounter.Add(1) if count == 1 { writeJSON(w, http.StatusBadRequest, tokenError{ErrorCode: tokenErrorCodePending}) break } fallthrough case "immediate-success": writeJSON(w, http.StatusOK, oauth2.Token{ AccessToken: staticAccessToken, TokenType: "Bearer", ExpiresIn: int64(time.Hour / time.Second), // 1h in seconds }) default: panic(fmt.Sprintf("unknown mode: %q", mode)) } }) return ts } func writeJSON(w http.ResponseWriter, statusCode int, v any) { b, err := json.Marshal(v) if err != nil { // should never happen http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) w.Write(b) } const ( // Device flow token error code strings from https://datatracker.ietf.org/doc/html/rfc8628#section-3.5 tokenErrorCodePending = "authorization_pending" // waiting for user tokenErrorCodeSlowDown = "slow_down" // increase polling interval tokenErrorCodeDenied = "access_denied" // the user denied the request tokenErrorCodeExpired = "expired_token" // the device_code expired ) // tokenError implements the error response structure defined by // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 type tokenError struct { ErrorCode string `json:"error"` // one of the constants above ErrorDescription string `json:"error_description,omitempty"` ErrorURI string `json:"error_uri,omitempty"` } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/000077500000000000000000000000001474664451600203735ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/mod/000077500000000000000000000000001474664451600211525ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/mod/externalmod.test_imports_v1.0.0.txtar000066400000000000000000000006551474664451600302230ustar00rootroot00000000000000-- .mod -- module externalmod.test/imports -- .info -- {"Version":"v1.0.0","Time":"2018-10-22T18:45:39Z"} -- go.mod -- module externalmod.test/imports -- root/p.go -- package root import "externalmod.test/imports/sub1" type Type struct { Sub1 sub1.Type } -- sub1/p.go -- package sub1 import "externalmod.test/imports/sub2" type Type struct { Sub2 sub2.Type } -- sub2/p.go -- package sub2 type Type struct { Leaf int } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/mod/externalmod.test_mixfiles_v1.0.0.txtar000066400000000000000000000012241474664451600303370ustar00rootroot00000000000000-- .mod -- module externalmod.test/mixfiles -- .info -- {"Version":"v1.0.0","Time":"2018-10-22T18:45:39Z"} -- go.mod -- // A module which mixes CUE, Go, and other files, to be tested with `cue get go`. module externalmod.test/mixfiles -- aa_first_noextension -- Mix an uninteresting file at the beginning of the directory list to verify that we don't stop looking at the rest of the files. -- code_one.go -- package mixfiles // Some fruit const NameOne = "Orange" -- code_two.go -- package mixfiles const NameTwo = "Apple" -- config_one.cue -- package mixfiles Type: "Fruit" -- config_two.cue -- package mixfiles Type: string -- zz_last_noextension -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/000077500000000000000000000000001474664451600216775ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cl-1204137.txtar000066400000000000000000000012641474664451600242030ustar00rootroot00000000000000# reproduction for https://review.gerrithub.io/c/cue-lang/cue/+/1204137 exec cue def -l '#Pipeline:' jsonschema: schema.json cmp stdout expect-stdout -- schema.json -- { "$id": "https://foo.com/this-id-is-required-to-reproduce-the-case", "type": "object", "properties": { "a": { "$ref": "#/definitions/User" } }, "definitions": { "User": { "type": "object", "additionalProperties": false, "properties": { "name": { "type": "string" } } } } } -- expect-stdout -- #Pipeline: { @jsonschema(id="https://foo.com/this-id-is-required-to-reproduce-the-case") a?: #User #User: close({ name?: string }) ... } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_after.txtar000066400000000000000000000017051474664451600247120ustar00rootroot00000000000000exec cue cmd after cmp stdout expect-stdout -- expect-stdout -- run also run true SUCCESS -- after_tool.cue -- package home import ( "tool/exec" "tool/cli" "strings" ) top0: cli.Print & { text: "run also" } top1: cli.Print & { text: "run", $after: top0 } top2: cli.Print & { text: "don't run also" } top3: cli.Print & { text: "don't", $after: top2 } command: after: { group: { t1: exec.Run & { cmd: ["sh", "-c", "sleep 2; date +%s"] stdout: string $after: top1 } t2: exec.Run & { cmd: ["sh", "-c", "date +%s"] stdout: string $after: t1 } } t3: exec.Run & { cmd: ["sh", "-c", "a=\(strings.TrimSpace(group.t1.stdout));b=\(strings.TrimSpace(group.t2.stdout));if [ $a -le $b ]; then echo 'true'; fi"] stdout: string } t4: cli.Print & { text: t3.stdout } t5: cli.Print & { text: "SUCCESS" $after: [ group, t4 ] } } -- task.cue -- package home -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_baddisplay.txtar000066400000000000000000000006051474664451600257230ustar00rootroot00000000000000! exec cue cmd baddisplay ! stdout . cmp stderr cmd_baddisplay.out -- cmd_baddisplay.out -- command.baddisplay.display.text: conflicting values 42 and string (mismatched types int and string): ./task_tool.cue:6:9 tool/cli:4:9 -- task.cue -- package home message: "Hello world!" -- task_tool.cue -- package home command: baddisplay: { display: { kind: "print" text: 42 } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_closed.txtar000066400000000000000000000004621474664451600250610ustar00rootroot00000000000000exec cue cmd run -- task.cue -- package ci // Must have // - indirection through definition // - unification of two list elements // - one of those elements must be _ // - Must use merge and unify tool file workflows: #Workflow #Workflow: ["a"] & [_] -- task_tool.cue -- package ci command: run: { } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_concurrent.txtar000066400000000000000000000011201474664451600257620ustar00rootroot00000000000000exec cue cmd runtwo cmp stdout runtwo-stdout -- runtwo-stdout -- foo: wrote foo and found bar bar: wrote bar and found foo -- runtwo_tool.cue -- package hello import ( "tool/cli" ) command: runtwo: { foo: { kind: "exec" cmd: ["testcmd", "concurrent", "foo", "bar"] stdout: string } bar: { kind: "exec" cmd: ["testcmd", "concurrent", "bar", "foo"] stdout: string } results: cli.Print & { text: "foo: \(foo.stdout)\nbar: \(bar.stdout)" } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_cycle.txtar000066400000000000000000000041521474664451600247070ustar00rootroot00000000000000# Issue #2416 exec cue cmd kube issue2397_tool.cue issue2397.cue cmp stdout stdout2397.golden # cycle on complete error ! exec cue cmd build issue2416a_tool.cue cmp stderr stderr2416.golden # cycle on incomplete error exec cue cmd print issue2416b_tool.cue cmp stdout stdout2416.golden -- issue2397.cue -- package test #obj: { requests?: { memory?: int & <=limits.memory } limits?: { memory?: int & <=100Gi } } // Stack overflow, but only in `cue cmd`. obj: #obj & { requests: memory: 1Gi // The problem in the original bug report was with this reference. limits: memory: requests.memory } -- issue2397_tool.cue -- package test import ( "encoding/yaml" "tool/cli" ) command: kube: { task: print: cli.Print & { text: yaml.Marshal(obj) } } -- issue2416a_tool.cue -- package kubecluster Cluster: {} m: x: Cluster m: x: X={ foobar: X.name name: "x" foo: string } dnsRecords: _ for _, X in m { dnsRecords: "\(m.x.foo)": "127.0.0.1" } command: build: { $id: "tool/file.Create" filename: "output/dns-records.zone" permissions: int | *0o666 let lines = [ for name, addr in dnsRecords { "\(name) A \(addr)" }, ] contents: lines[0] } -- issue2416b_tool.cue -- package p import ( "strings" "tool/cli" ) #Input: INPUT={ kind: string outKey: string | *"default" if kind != "foo" { outKey: INPUT.kind } } inputs: f: #Input & { kind: "foo" } inputs: b: #Input & { kind: "bar" } outputs: [string]: string for _, input in inputs { outputs: "\(input.outKey)": input.kind } command: print: cli.Print & { text: strings.Join([for key, val in outputs { "key=\(key) val=\(val)" }], "\n") } -- stdout2397.golden -- requests: memory: 1073741824 limits: memory: 1073741824 -- stderr2416.golden -- command.build.contents: invalid bytes argument: invalid interpolation: non-concrete value string (type string): ./issue2416a_tool.cue:18:10 ./issue2416a_tool.cue:9:7 ./issue2416a_tool.cue:15:14 ./issue2416a_tool.cue:27:2 -- stdout2416.golden -- key=default val=foo key=bar val=bar cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_debug.txtar000066400000000000000000000013151474664451600246740ustar00rootroot00000000000000env CUE_DEBUG_TOOLS_FLOW=1 exec cue cmd bar cmp stderr stderr.golden -- x_tool.cue -- package x import ( "tool/cli" ) command: bar: { a: cli.Print & { text: "a" } "\"b#": cli.Print & { text: "b" $after: a } } -- stderr.golden -- tools/flow task dependency graph: ```mermaid graph TD t0("command.bar.a [Ready]") t1("command.bar.#quot;\#quot;b#35;#quot; [Waiting]") t1-->t0 ``` tools/flow task dependency graph: ```mermaid graph TD t0("command.bar.a [Terminated]") t1("command.bar.#quot;\#quot;b#35;#quot; [Ready]") t1-->t0 ``` tools/flow task dependency graph: ```mermaid graph TD t0("command.bar.a [Terminated]") t1("command.bar.#quot;\#quot;b#35;#quot; [Terminated]") t1-->t0 ``` cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_dep.txtar000066400000000000000000000010321474664451600243520ustar00rootroot00000000000000exec cue cmd do cmp stdout expect-stdout -- expect-stdout -- {"b":"cue"} -- task_tool.cue -- package home import ( "encoding/json" "strings" "tool/cli" "tool/exec" ) foo: { #a: string b: #a } command: do: { inputs: name: exec.Run & { cmd: "echo cue" stdout: string } outputs: print: cli.Print & { text: json.Marshal(foo & { #a: strings.TrimSpace(inputs.name.stdout) }) } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_dep_cycle.txtar000066400000000000000000000015731474664451600255430ustar00rootroot00000000000000! exec cue cmd cycle cmp stderr expect-stderr1 ! exec cue cmd aftercycle cmp stderr expect-stderr2 exec cue cmd interlockedTasks cmp stdout interlocked-stdout cmp stderr expect-stderr3 -- expect-stderr1 -- cyclic task dependency: task command.cycle.t1 refers to task command.cycle.t2 refers to task command.cycle.t1: ./after_tool.cue:18:2 ./after_tool.cue:19:2 -- expect-stderr2 -- command.aftercycle.t1.$after.$after: structural cycle -- expect-stderr3 -- -- interlocked-stdout -- v v -- after_tool.cue -- package home import ( "tool/cli" ) command: interlockedTasks: { t1: cli.Print & { text: t2.value, value: "v" } t2: cli.Print & { text: t1.value, value: "v" } } command: aftercycle: { t1: cli.Print & { $after: t2, text: "t1" } t2: cli.Print & { $after: t1, text: "t2" } } command: cycle: { t1: cli.Print & { text: t2.text } t2: cli.Print & { text: t1.text } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_depissue.txtar000066400000000000000000000010231474664451600254230ustar00rootroot00000000000000# Issue #3646 env CUE_EXPERIMENT=evalv3=0 exec cue cmd two stdout 'msg.*hello' env CUE_EXPERIMENT=evalv3=1 exec cue cmd two stdout 'msg.*hello' -- input_tool.cue -- package p import ( "tool/exec" "encoding/json" ) command: { one: exec.Run & { stdin: "{\"msg\": \"hello\"}" cmd: ["cat"] stdout: string } two: exec.Run & { let data = json.Unmarshal(one.stdout) cmd: ["cat"] // "true" is printed for each json value read stdin: json.Marshal(data) + "\n" } }cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_deppkg.txtar000066400000000000000000000005641474664451600250650ustar00rootroot00000000000000exec cue cmd foo cmp stdout cue_cmd_foo_both.golden -- cue.mod/module.cue -- module: "mod.test/test" language: version: "v0.9.0" -- sub/sub.cue -- package sub User: "sub" -- x_tool.cue -- package x import ( "tool/cli" "mod.test/test/sub" ) command: foo: cli.Print & { text: "test \(sub.User)" } -- cue_eval.golden -- x: "sub" -- cue_cmd_foo_both.golden -- test subcue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_dir.txtar000066400000000000000000000006061474664451600243660ustar00rootroot00000000000000exec cue cmd ls cmp stdout expect-stdout -- expect-stdout -- a.txt b.txt -- ls-work-dir/a.txt -- -- ls-work-dir/b.txt -- -- ls_tool.cue -- package ls command: ls: { ls: { kind: "exec" cmd: "ls" dir: "ls-work-dir" stdout: string } task: display: { kind: "print" text: ls.stdout } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_echo.txtar000066400000000000000000000013441474664451600245260ustar00rootroot00000000000000exec cue cmd echo stdout 'Hello World!' exec cue cmd echohidden stdout 'Hello World!' -- cue.mod/module.cue -- module: "mod.test/foo" language: version: "v0.9.0" -- data.cue -- package hello _who: "World" -- hello.cue -- package hello message: "Hello \(_who)!" // who declared in data.cue -- hello_tool.cue -- package hello command: echo: { echo: { kind: "exec" cmd: "echo \(message)" stdout: string } task: display: { kind: "print" text: echo.stdout } } // Issue #924 command: echohidden: { echo: { kind: "exec" cmd: "echo Hello \(_who)!" stdout: string } task: display: { kind: "print" text: echo.stdout } }cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_embed.txtar000066400000000000000000000025341474664451600246660ustar00rootroot00000000000000# Issue #281 # Verify that we get the expected exported output. exec cue export cmp stdout expect/concrete.json # Using the explicitly written command works OK. exec cue cmd hello1 stdout 'hello, world' # Using the command that's defined externally fails. exec cue cmd hello stdout 'hello, world' -- expect/concrete.json -- { "command": { "hello": { "task": { "hello": { "$id": "tool/cli.Print", "text": "hello, world" } } }, "hello1": { "task": { "hello": { "$id": "tool/cli.Print", "text": "hello, world" } } } } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- cue.mod/pkg/mod.test/hello/cue.mod/module.cue -- module: "mod.test/hello" -- cue.mod/pkg/mod.test/hello/hello.cue -- package hello import "tool/cli" command: hello: task: hello: cli.Print & { text: "hello, world" } -- m.cue -- package x import ( "tool/cli" "mod.test/hello" ) hello command: hello1: task: hello: cli.Print & { text: "hello, world" } -- x_tool.cue -- package x import ( "tool/cli" "mod.test/hello" ) // This should pull in the hello task. hello command: hello1: task: hello: cli.Print & { text: "hello, world" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_env.txtar000066400000000000000000000005121474664451600243740ustar00rootroot00000000000000env TESTNUM=10 env MYTEXT=World exec cue cmd env cmp stdout cmd_env.out -- cmd_env.out -- Hello World! -- task_tool.cue -- package home import ( "tool/os" "tool/cli" ) command: env: { env: os.Getenv & { TESTNUM: *<10 | string MYTEXT: string } print: cli.Print & { text: "Hello \(env.MYTEXT)!" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_err.txtar000066400000000000000000000010211474664451600243700ustar00rootroot00000000000000! exec cue cmd ref ! stdout . cmp stderr cmd_badfields.out -- cmd_badfields.out -- command.ref.task.display.contents: invalid bytes argument: non-concrete value (string|bytes): ./task_tool.cue:6:8 tool/file:17:3 command.ref.task.display.filename: invalid string argument: non-concrete value string: ./task_tool.cue:6:8 ./task_tool.cue:7:9 tool/file:15:3 tool/file:15:16 -- task_tool.cue -- package home import "tool/file" command: ref: { task: display: file.Create & { filename: filename } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_errcode.txtar000066400000000000000000000005451474664451600252350ustar00rootroot00000000000000! exec cue cmd errcode ! stdout . stderr '^task failed: command \["ls" "--badflags"\] failed: exit status [12]$' -- task.cue -- package home message: "Hello world!" -- task_tool.cue -- package home import "tool/exec" command: errcode: { task: bad: exec.Run & { kind: "exec" cmd: "ls --badflags" stderr: string // suppress error message } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_errpos.txtar000066400000000000000000000012671474664451600251260ustar00rootroot00000000000000! exec cue cmd prompter cmp stderr expect-stderr # Issue #479 -- expect-stdout -- -- expect-stderr -- command.prompter.contents: invalid bytes argument: non-concrete value string: ./task_tool.cue:9:10 ./task_tool.cue:12:13 ./task_tool.cue:17:3 tool/file:11:3 command.prompter.filename: invalid string argument: non-concrete value string: ./task_tool.cue:9:10 tool/file:9:3 tool/file:9:16 -- task_tool.cue -- package foo import ( "tool/cli" "tool/file" ) command: prompter: { ask: cli.Ask & { prompt: "What is your name?" response: string } // inadvertently defined at top level, masking other tasks. file.Append & { contents: ask.response } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_execenv.txtar000066400000000000000000000017131474664451600252450ustar00rootroot00000000000000exec cue cmd execEnv cmp stdout stdout.golden -- cue.mod/module.cue -- module: "example.com" language: version: "v0.9.0" -- stdout.golden -- usesDefaultsStruct: hello from John Doe usesDefaultsList: hello from John Doe -- foo_tool.cue -- package foo import ( "tool/cli" "tool/exec" ) #messageText: *"hello" | string message: *"MESSAGE=\(#messageText)" | string command: execEnv: { usesDefaultsStruct: exec.Run & { cmd: ["sh", "-c", "echo $MESSAGE from $SENDER"] stdout: *"" | string env: { MESSAGE: #messageText SENDER: *"John Doe" | string } } usesDefaultsList: exec.Run & { cmd: ["sh", "-c", "echo $MESSAGE from $SENDER"] stdout: *"" | string env: [message, *"SENDER=John Doe" | string ] } result: cli.Print & { text: """ usesDefaultsStruct: \(usesDefaultsStruct.stdout) usesDefaultsList: \(usesDefaultsList.stdout) """ } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_execerr.txtar000066400000000000000000000022561474664451600252500ustar00rootroot00000000000000! exec cue cmd cannotFail cmp stderr cannotFail-stderr.golden exec cue cmd canFail cmp stdout canFail-stdout.golden ! exec cue cmd withSpaces cmp stderr withSpaces-stderr.golden -- cue.mod/module.cue -- module: "example.com" language: version: "v0.9.0" -- cannotFail-stderr.golden -- task failed: command ["false"] failed: exit status 1 -- canFail-stdout.golden -- errExit: success=false hasStderr=false errNotFound: success=false hasStderr=true -- withSpaces-stderr.golden -- task failed: command ["false" "with an ignored argument"] failed: exit status 1 -- foo_tool.cue -- package foo import ( "tool/cli" "tool/exec" ) command: cannotFail: { one: exec.Run & { cmd: ["false"] } } command: canFail: { errExit: exec.Run & { cmd: ["false"] stderr: string mustSucceed: false } errNotFound: exec.Run & { cmd: ["program-does-not-exist"] stderr: string mustSucceed: false } second: cli.Print & { text: """ errExit: success=\(errExit.success) hasStderr=\(errExit.stderr != "") errNotFound: success=\(errNotFound.success) hasStderr=\(errNotFound.stderr != "") """ } } command: withSpaces: exec.Run & { cmd: ["false", "with an ignored argument"] } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_filetypes.txtar000066400000000000000000000045431474664451600256200ustar00rootroot00000000000000# An empty argument is not a valid package pattern nor filename. ! exec cue export '' stderr 'empty file name' # Unknown filetype prefix. ! exec cue export cue+date: somefile.cue stderr 'unknown filetype date' # Trying to parse as the wrong filetype. ! exec cue export json: somefile.cue stderr 'invalid JSON for file' # Trying to parse as the explicitly right filetype. exec cue export cue: somefile.cue cmp stdout export.golden # Filetype detection works with absolute or relative paths, including dot prefixes. exec cue export somefile.cue cmp stdout export.golden exec cue export ./somefile.cue cmp stdout export.golden exec cue export ${WORK}${/}somefile.cue cmp stdout export.golden # A package can be loaded as a pattern or as a directory, with or without trailing slashes. exec cue export ./somepkg cmp stdout export.golden exec cue export ./somepkg/ cmp stdout export.golden # TODO(mvdan): we should support loading packages from absolute directories. ! exec cue export ${WORK}${/}somepkg [!windows] stderr 'cannot use absolute directory ".*somepkg" as package path' [windows] stderr 'no encoding specified for file ".*somepkg.*"' ! exec cue export ${WORK}${/}somepkg${/} [!windows] stderr 'cannot use absolute directory ".*somepkg/" as package path' [windows] stderr 'no encoding specified for file ".*somepkg.*"' # Now do some of the same filename tests, but for a file without any extension. cp somefile.cue somefile ! exec cue export json: somefile stderr 'invalid JSON for file' exec cue export cue: somefile cmp stdout export.golden exec cue export cue: ./somefile cmp stdout export.golden exec cue export cue: ${WORK}${/}somefile cmp stdout export.golden # Without an extension nor a filetype, "somefile" on its own looks like a std package. ! exec cue export somefile stderr 'standard library import path "somefile" cannot be imported as a CUE package' ! exec cue export ./somefile stderr '\./somefile is a file and not a package directory' # TODO(mvdan): we probably should not behave differently on Windows. ! exec cue export ${WORK}${/}somefile [!windows] stderr 'cannot use absolute directory ".*somefile" as package path' [windows] stderr 'no encoding specified for file ".*somefile"' -- cue.mod/module.cue -- module: "mod.test/test" language: version: "v0.9.0" -- somefile.cue -- a: 5 -- somepkg/somefile.cue -- package somepkg a: 5 -- export.golden -- { "a": 5 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_func.txtar000066400000000000000000000005211474664451600245370ustar00rootroot00000000000000# Issue #578 exec cue cmd dump ./... cmp stdout stdout-expect -- k1.cue -- package kube import "encoding/json" x: y: 2 objects: [for v in [json.Marshal(x)] {v}] -- k_tool.cue -- package kube import ( "tool/cli" "encoding/json" ) command: dump: cli.Print & { text: json.MarshalStream(objects) } -- stdout-expect -- "{\"y\":2}" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_http.txtar000066400000000000000000000010341474664451600245630ustar00rootroot00000000000000exec cue cmd http cmp stdout cmd_http.out -- cmd_http.out -- {"data":"I'll be back!","when":"now"} -- task_tool.cue -- package home import ( h "tool/http" "tool/cli" ) command: http: { task: testserver: { kind: "testserver" url: string } task: http: h.Post & { url: task.testserver.url request: body: "I'll be back!" response: body: string // TODO: allow this to be a struct, parsing the body. } task: print: cli.Print & { text: task.http.response.body } } -- task.cue -- package home message: "Hello world!" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_import.txtar000066400000000000000000000005041474664451600251170ustar00rootroot00000000000000! exec cue cmd pkg cmp stderr expect-stderr -- expect-stderr -- command.pkg.t: reference "cli" not found: ./task_tool.cue:6:5 -- task_tool.cue -- package home // missing imports command: pkg: { t: cli.Print & { text: "Hello world!" } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_inferred.txtar000066400000000000000000000007721474664451600254120ustar00rootroot00000000000000exec cue cmd dump cmp stdout expect-stdout -- f1.cue -- package kube pkg: { #Def: { a: int b: #Role } #Role: { kind: string name: string } } test: pkg.#Def test: { a: 1 b: { kind: "foo" name: "bar" } } // A kind at the top-level should not be allowed. kind: "foo" $id: "bar" -- dump_tool.cue -- package kube import ( "tool/cli" "encoding/yaml" ) command: dump: { task: print: cli.Print & { text: yaml.Marshal(test) } } -- expect-stdout -- a: 1 b: kind: foo name: bar cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_issue1405.txtar000066400000000000000000000007611474664451600252540ustar00rootroot00000000000000exec cue cmd alias ./alias_tool.cue cmp stdout stdout-golden -- alias_tool.cue -- import ( "tool/exec" "text/template" ) command: alias: { rendered: template.Execute(t, instance & { enabled: true }) echo: exec.Run & { cmd: ["echo", rendered] } } t: """ # {{ .name }} """ #base: { enabled: bool | *false name: string value?: int } #combined: X=#base & { name: "OK" if X.enabled { value: 123456 } } instance: #combined & { enabled: true } -- stdout-golden -- # OK cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_issue2060.txtar000066400000000000000000000064411474664451600252530ustar00rootroot00000000000000exec cue cmd tangle_sublime cmp stdout stdout1.golden exec cue cmd ts cmp stdout stdout2.golden -- tangle_sublime_tool.cue -- package tangle_sublime import ( "encoding/yaml" "tool/cli" ) command: tangle_sublime: { debugSourceFile: cli.Print & {text: yaml.Marshal(buildSource)} } v: w: 0 let X = {c: d: v} a: b: X.c command: ts: cli.Print & {text: "foo", x: a} -- other.cue -- package tangle_sublime import ( "strings" "list" ) keyzen: KeyZen: { Commands: { CommandNames: ["CursorMoveToLineForward"] CommandDetailsMap: { CursorMoveToLineForward: { Human: "Cursor Down" Category: "Cursor" Subcategory: "" } } } Editors: { SublimeText: { EditorCommandNameMap: { CursorMoveToLineForward: { command: "move" // delete this line to remove panic argsText: "test" } } } } Strokes: { ZenStrokes1: { Name: "ZenStrokes1" StrokeCmdDefsMap: { CursorMoveToLineForward: [["Down"], ["Hyper+K"]] } StrokesMap: { CursorMoveToLineForward: [{ Bindings: { Linux: { Down: 10 } } DefText: "Down" }] } } } } args: { editorName: "SublimeText" strokesName: "ZenStrokes1" platformName: "Linux" fileName: "_" + strings.ToLower(editorName) + "_strokes.json5" } cmdNames: keyzen.KeyZen.Commands.CommandNames editorCmds: keyzen.KeyZen.Editors["\(args.editorName)"].EditorCommandNameMap strokeCmdsMap: keyzen.KeyZen.Strokes["\(args.strokesName)"].StrokesMap buildSource: { EditorName: args.editorName StrokesName: args.strokesName PlatformName: args.platformName CommandBindingsCount: len(CommandBindings) CommandBindings: [ for cmdIdx, cmdName in cmdNames if keyzen.KeyZen.Strokes[StrokesName].StrokesMap[cmdName] != _|_ && editorCmds[cmdName] != _|_ { let cmdDetails = keyzen.KeyZen.Commands.CommandDetailsMap[cmdName] let strokeDefs = keyzen.KeyZen.Strokes[StrokesName].StrokesMap[cmdName] let editorCmd = editorCmds[cmdName] let editorCmdText = editorCmd.argsText let editorCmdTextCommand = "\"command\": \"" + editorCmd.command + "\"" CmdName: cmdName CmdHumanName: cmdDetails["Human"] EditorCmdText: string if editorCmdText == _|_ {EditorCmdText: editorCmdTextCommand} if editorCmdText != _|_ {EditorCmdText: editorCmdTextCommand + ", \"args\": " + editorCmd.argsText} BindingsCount: len(Bindings) if BindingsCount == 0 {{BindingsMax: 0}} if BindingsCount > 0 {{BindingsMax: BindingsCount - 1}} Bindings: [ for _, strokeDef in strokeDefs { let bindingMap = strokeDef.Bindings["\(PlatformName)"] let bindingIds = [for k, v in bindingMap {name: k, idx: v}] let bindingIdsSorted = list.Sort(bindingIds, {x: {}, y: {}, less: x.idx < y.idx}) let bindingKeys = [for _, kv in bindingIdsSorted {kv.name}] let bindingText = strings.Join(bindingKeys, "+") "DefText": "\(strokeDef.DefText)" "BindText": bindingText }, ] }, ] } -- stdout1.golden -- EditorName: SublimeText StrokesName: ZenStrokes1 PlatformName: Linux CommandBindingsCount: 1 CommandBindings: - BindingsMax: 0 CmdName: CursorMoveToLineForward CmdHumanName: Cursor Down EditorCmdText: '"command": "move", "args": test' BindingsCount: 1 Bindings: - DefText: Down BindText: Down -- stdout2.golden -- foo cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_issue650.txtar000066400000000000000000000005751474664451600252000ustar00rootroot00000000000000exec cue cmd test -- blah/blah.cue -- package blah #Pod: { spec?: #PodSpec } #PodSpec: { } -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- x_tool.cue -- package kube import ( "tool/cli" "mod.test/blah" ) root: blah.#Pod root: spec: _ command: test: task: test: cli.Print & { for _ in root { text: "success" } } -- y_tool.cue -- package kubecue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_jsonpb.txtar000066400000000000000000000026571474664451600251130ustar00rootroot00000000000000exec cue eval schema.cue json+pb: data.json cmp stdout out/data1 exec cue eval schemaflag.cue -d '#X' json+pb: data.json cmp stdout out/data1 ! exec cue eval schema.cue json+pb: data-err.json cmp stderr out/data-err exec cue eval .:nested yaml+pb: stream.yaml -l kind cmp stdout out/stream -- schema.cue -- a: int @protobuf(1,int64) // to string b: int @protobuf(2,int32) // also allow string c: int // also allow d: float s: string t: bytes -- nested.cue -- package nested A: { a: int @protobuf(1,int64) // to string b: bytes } B: { a: int @protobuf(1,int64) // to string s: string } -- schemaflag.cue -- #X: { a: int @protobuf(1,int64) // to string b: int @protobuf(2,int32) // also allow string c: int // also allow d: float s: string t: bytes } -- data.json -- {"a": "10", "b": "20", "c": 30, "d": "1.2", "s":"SGVsbG8sIOS4lueVjA==", "t": "SGVsbG8sIOS4lueVjA=="} -- data-err.json -- {"a": "10", "b": "20", "c": "30", "t": "SGVsbG8sIOS4lue???VjA==" } -- stream.yaml -- kind: "A" a: "10" b: "SGVsbG8sIOS4lueVjA==" --- kind: "B" a: "10" s: "SGVsbG8sIOS4lueVjA==" -- out/data1 -- a: 10 b: 20 c: 30 d: 1.2 s: "SGVsbG8sIOS4lueVjA==" t: 'Hello, 世界' -- out/stream -- A: { kind: "A" a: 10 b: 'Hello, 世界' } B: { kind: "B" a: 10 s: "SGVsbG8sIOS4lueVjA==" } -- out/data-err -- t: failed to decode base64: illegal base64 data at input byte 15: ./data-err.json:1:40 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_many.txtar000066400000000000000000000033621474664451600245560ustar00rootroot00000000000000# Test cue cmd's behavior when given multiple packages. # Note that we're not sure if this is the behavior we want long term, # but it is the behavior we have had for some time, and some users # are currently reliant on it. See https://cuelang.org/issue/1325. # Export with itemsList_tool.cue in place. exec cue export ./... cmp stdout stdout.export-pre.golden # Verify that cue cmd ls ./... works. # Note that a single ls command is run with a single package value # reuslting from the unification of all packages in ./... exec cue cmd ls ./... cmp stdout stdout.ls-pre.golden # Now rename itemsList_tool.cue to itemsList.cue. mv itemsList_tool.cue itemsList.cue # Export with itemsList.cue in place. exec cue export ./... cmp stdout stdout.export-post.golden # Attempt to ls in this state, which fails, as each of the CUE packages # hold an items list with different lengths. ! exec cue cmd ls ./... stderr 'itemsList: incompatible list lengths \(0 and 1\)' -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- x.cue -- package x items: {} -- ls_tool.cue -- package x import ( "tool/cli" "strings" ) command: ls: cli.Print & { text: "ls: " + strings.Join(itemsList, " ") + "\n" } -- itemsList_tool.cue -- package x itemsList: [for _, v in items {v}] -- a/x.cue -- package x items: { a: "a" } -- b/x.cue -- package x items: { b: "b" } -- stdout.export-pre.golden -- { "items": {} } { "items": { "a": "a" } } { "items": { "b": "b" } } -- stdout.ls-pre.golden -- ls: a b -- stdout.export-post.golden -- { "items": {}, "itemsList": [] } { "items": { "a": "a" }, "itemsList": [ "a" ] } { "items": { "b": "b" }, "itemsList": [ "b" ] } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_mkdirtmp.txtar000066400000000000000000000004451474664451600254400ustar00rootroot00000000000000exec cue cmd mkdirtmp -- mkdir_tool.cue -- package mkdirtmp import ( "tool/file" ) command: mkdirtmp: { tmp: file.MkdirTemp & { path: string } rm: file.RemoveAll & { path: tmp.path success: true } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_modules.txtar000066400000000000000000000011321474664451600252530ustar00rootroot00000000000000exec cue cmd print cmp stdout expect-stdout -- expect-stdout -- hello, world -- task_tool.cue -- package home import ( "tool/cli" textPkg "foo.example/text" ) command: print: { print: cli.Print & { text: "hello, \(textPkg.value)" } } -- cue.mod/module.cue -- module: "main.example" language: version: "v0.8.0" deps: "foo.example/text@v0": { default: true v: "v0.0.1" } -- task.cue -- package home -- _registry/foo.example_text_v0.0.1/cue.mod/module.cue -- module: "foo.example/text@v0" language: version: "v0.8.0" -- _registry/foo.example_text_v0.0.1/text.cue -- package text value: "world" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_notool.txtar000066400000000000000000000005431474664451600251220ustar00rootroot00000000000000! exec cue cmd notool ! stdout . cmp stderr cmd_baddisplay.out -- cmd_baddisplay.out -- could not find command "notool" Ensure custom commands are defined in a "_tool.cue" file. Run 'cue help cmd' to list available custom commands. -- task.cue -- package home message: "Hello world!" command: notool: { task: display: { kind: "print" text: 42 } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_order.txtar000066400000000000000000000002721474664451600247220ustar00rootroot00000000000000exec cue cmd gen -- task_tool.cue -- package ci command: gen: { $id: "tool/cli.Print" text: { #early: *"X" | string #early } & {// NEEDED #early: *"X" | string string } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_print.txtar000066400000000000000000000013151474664451600247420ustar00rootroot00000000000000env CUE_EXPERIMENT=evalv3=0 exec cue cmd print cmp stdout expect-stdout env CUE_EXPERIMENT=evalv3=1 exec cue cmd print cmp stdout expect-stdout -- expect-stdout -- t.1. .t.2. -- task_tool.cue -- package home import ( "tool/exec" "tool/cli" "strings" ) command: print: { runs: t1: exec.Run & { cmd: ["sh", "-c", "sleep 1; echo t1"] stdout: string } runs: t2: exec.Run & { cmd: ["sh", "-c", "sleep 1; echo t2"] stdout: string } print: cli.Print & { text: (#f & {arg: runs.t1.stdout + runs.t2.stdout}).result } } #f: { arg: string result: strings.Join(strings.Split(arg, ""), ".") } -- task.cue -- package home -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_ref.txtar000066400000000000000000000006141474664451600243630ustar00rootroot00000000000000exec cue cmd ref cmp stdout expect-stdout -- expect-stdout -- hello -- task_tool.cue -- package home import ( "tool/cli" "tool/exec" ) command: ref: { t1: exec.Run & { ref: t1.stdout cmd: ["sh", "-c", "echo hello"] stdout: string } t2: cli.Print & { text: t1.stdout } } -- task.cue -- package home -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_run.txtar000066400000000000000000000007421474664451600244150ustar00rootroot00000000000000exec cue cmd run stdout 'Hello world!' -- task.cue -- package home message: "Hello world!" -- task_tool.cue -- package home command: run: #RunBase & { task: echo: cmd: "echo \(message)" } -- base_tool.cue -- package home import ( "tool/cli" "tool/exec" ) // deliberately put in another file to test resolving top-level identifiers // in different files. #RunBase: { task: echo: exec.Run & { stdout: string } task: display: cli.Print & { text: task.echo.stdout } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_run_list.txtar000066400000000000000000000007171474664451600254520ustar00rootroot00000000000000exec cue cmd run_list stdout 'Hello world!' -- task.cue -- package home message: "Hello world!" -- task_tool.cue -- package home command: run_list: runBase & { task: echo: cmd: ["echo", message] } -- base_tool.cue -- package home // deliberately put in another file to test resolving top-level identifiers // in different files. runBase: { task: echo: { kind: "exec" stdout: string } task: display: { kind: "print" text: task.echo.stdout } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_short.txtar000066400000000000000000000003771474664451600247540ustar00rootroot00000000000000exec cue cmd hello stdout 'Hello world!' ! stderr . ! exec cue hello cmp stderr short-stderr -- short-stderr -- unknown command "hello" for "cue" -- task_tool.cue -- package home import "tool/cli" command: hello: cli.Print & { text: "Hello world!" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_stdin.txtar000066400000000000000000000040671474664451600247360ustar00rootroot00000000000000# Executing a program that consumes all of stdin. stdin echo-stdin exec cue cmd echo cmp stdout echo-stdout # A command with two prompts, where the input is three lines. # The first and second line should be the two answers. stdin intro-stdin exec cue cmd intro cmp stdout intro-stdout # Like the previous test case, but with more whitespace in the answers. # The response strings should contain the entire lines including the whitespace. stdin intro-spaces-stdin exec cue cmd intro cmp stdout intro-spaces-stdout # Run a command with exec.Run which doesn't actually read stdin, # but still passes through stdin to os/exec per exec.Run's default. # This will hang unless the task's stdin is an os.File, # as otherwise io.Copy does not finish; see https://go.dev/issue/7990. exec cue_stdinpipe cmd noreads cmp stdout noreads-stdout -- echo-stdin -- Hello World! -- echo-stdout -- Hello World! -- intro-stdin -- John Doe Capital City Extra input that shouldn't be used. -- intro-stdout -- What is your name? Where do you live? Your full name is John Doe and you live in Capital City. -- intro-spaces-stdin -- John Doe Capital City Extra input that shouldn't be used. -- intro-spaces-stdout -- What is your name? Where do you live? Your full name is John Doe and you live in Capital City. -- noreads-stdout -- not reading any stdin -- hello_tool.cue -- package hello import ( "tool/cli" "tool/exec" ) command: echo: { echo: { kind: "exec" cmd: "cat" stdout: string } pass: { kind: "exec" cmd: "cat" stdin: echo.stdout } } command: intro: { askName: cli.Ask & { prompt: "What is your name?" response: string } askPlace: cli.Ask & { order: askName.response prompt: "Where do you live?" response: string } results: cli.Print & { text: "\nYour full name is \(askName.response) and you live in \(askPlace.response)." } } command: noreads: { first: exec.Run & { cmd: ["echo", "not reading any stdin"] } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_tags.txtar000066400000000000000000000017311474664451600245460ustar00rootroot00000000000000exec cue cmd -t prod -t name=bar tag tags.cue tags_tool.cue cmp stdout expect-stdout # Check that the flags can be used after any arguments; # such "interspersed" flags are supported by cobra by default. exec cue cmd tag tags.cue tags_tool.cue -t prod -t name=bar cmp stdout expect-stdout # Verify that the new global -t flag added as a fix for issue 2510 above # works with the explicit or implicit "cmd" sub-command, # but not with other sub-commands like "fmt". exec cue eval -t name=bar tags.cue stdout 'name: *"bar"' exec cue -t name=bar eval tags.cue stdout 'name: *"bar"' ! exec cue fmt -t name=bar tags.cue stderr 'unknown shorthand flag' ! exec cue -t name=bar fmt tags.cue stderr 'unknown shorthand flag' -- expect-stdout -- prod: bar -- tags.cue -- package tags var: env: "prod" | "staging" @tag(env,short=prod|staging) var: name: string @tag(name) -- tags_tool.cue -- package tags import "tool/cli" command: tag: cli.Print & { text: "\(var.env): \(var.name)" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_textproto.txtar000066400000000000000000000014761474664451600256660ustar00rootroot00000000000000exec cue eval topschema.cue foo.textproto cmp stdout out/topfoo.textproto exec cue eval -d '#X' schema.cue foo.textproto cmp stdout out/foo.textproto ! exec cue eval -d '#X' schema.cue foo.textproto -l c cmp stderr out/stderr3 # This asserts the compatibility of Vertex.MatchAndInsert, which is only used # outside of the core evaluator. env CUE_EXPERIMENT=evalv3 exec cue eval topschema.cue foo.textproto cmp stdout out/topfoo.textproto -- topschema.cue -- a: int b: [...int] c: string -- schema.cue -- #X: { a: int b: [...int] c: string } -- foo.textproto -- a: 4 b: 1 b: 2 b: 3 b: 4 b: 5 c: "foo" -- out/topfoo.textproto -- a: 4 b: [1, 2, 3, 4, 5] c: "foo" -- out/foo.textproto -- a: 4 b: [1, 2, 3, 4, 5] c: "foo" -- out/stderr3 -- cannot combine --schema flag with flag "path", "list", or "files" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_textproto_required_optional.txtar000066400000000000000000000006441474664451600314670ustar00rootroot00000000000000exec cue eval input.textproto schema-required.cue cmp stdout want-stdout-required ! exec cue eval input.textproto schema-optional.cue cmp stderr want-stderr-optional -- input.textproto -- f: 234 -- schema-required.cue -- f!: int64 -- want-stdout-required -- f: 234 -- schema-optional.cue -- f?: string -- want-stderr-optional -- textproto: invalid string or bytes: invalid quote character 2: ./input.textproto:1:1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/cmd_undefined.txtar000066400000000000000000000012041474664451600255440ustar00rootroot00000000000000! exec cue cmd tool stderr 'command.tool.bad: undefined field: DoesntExist' ! exec cue cmd builtin stderr 'command.builtin.bad: undefined field: DoesntExist' ! exec cue cmd package stderr 'command.package.bad: undefined field: DoesntExist' -- cue.mod/module.cue -- module: "mod.test/test" language: version: "v0.9.0" -- sub/sub.cue -- package sub -- task_tool.cue -- package home import ( "tool/os" "strconv" "mod.test/test/sub" ) command: tool: { bad: os.DoesntExist & { input: "a" } } command: builtin: { bad: strconv.DoesntExist & { a: "b" } } command: package: { bad: sub.DoesntExist } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_basic.txtar000066400000000000000000000005361474664451600246660ustar00rootroot00000000000000exec cue def cmp stdout expect-stdout1 exec cue def data.cue cmp stdout expect-stdout2 -- schema.cue -- // foo package foo #A: { // a is an integer a: int b: { c: int } // TODO: should we _not_ simplify? } -- data.cue -- 3 -- expect-stdout2 -- 3 -- expect-stdout1 -- // foo package foo #A: { // a is an integer a: int b: c: int } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_comments.txtar000066400000000000000000000122441474664451600254310ustar00rootroot00000000000000exec cue def 1.cue cmp stdout stdout-1.cue exec cue def 2.cue cmp stdout stdout-2.cue exec cue def 2.cue -p t cmp stdout stdout-2-pkg.cue exec cue def 1.cue 2.cue cmp stdout stdout-1_2.cue exec cue def 2.cue 1.cue cmp stdout stdout-2_1.cue exec cue def 1.cue 3.cue cmp stdout stdout-1_3.cue exec cue def 3.cue 1.cue cmp stdout stdout-3_1.cue exec cue def 2.cue 4.cue cmp stdout stdout-2_4.cue exec cue def 2.cue 4.cue -p t cmp stdout stdout-2_4-pkg.cue # title and top description are lost exec cue def -l '#top:' jsonschema: schema1.json cmp stdout stdout1-def exec cue def jsonschema: schema1.json cmp stdout stdout1 # title and top description override a description exec cue def -l '#top:' jsonschema: schema2.json cmp stdout stdout2-def exec cue def jsonschema: schema2.json cmp stdout stdout2 # description of definition is lost exec cue def -l '#top:' issue3522.json stdout 'description of a field' stdout 'overall description' stdout 'description of foo' exec cue def issue3522.json stdout 'description of a field' stdout 'overall description' stdout 'description of foo' -- issue3522.json -- { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { "foo": { "description": "description of foo", "properties": { "a": { "description": "description of a field", "type": "number" } } } }, "description": "overall description", "$ref": "#/$defs/foo" } -- schema1.json -- { "title": "This is a title", "description": "top description", "properties": { "a": { "type": "object", "description": "a description", "properties": { "b": { "description": "b description", "type": "number" } } } } } -- stdout1 -- // This is a title // // top description null | bool | number | string | [...] | { // a description a?: { // b description b?: number ... } ... } -- stdout1-def -- // This is a title // // top description #top: null | bool | number | string | [...] | { // a description a?: { // b description b?: number ... } ... } -- schema2.json -- { "title": "This is a title", "description": "top description", "type": "object", "properties": { "a": { "type": "object", "description": "a description", "properties": { "b": { "description": "b description", "type": "number" } } } } } -- stdout2 -- // This is a title // // top description // a description a?: { // b description b?: number ... } ... -- stdout2-def -- // This is a title // // top description #top: { // a description a?: { // b description b?: number ... } ... } -- 1.cue -- // 1.cue: file comment // 1.cue: pkg doc comment package t // 1.cue: pkg comment 1 // 1.cue: pkg comment 2 // 1.cue: d comment d: 1 // 1.cue: d comment 1 di: 1 dii: 1 -- 2.cue -- // 2.cue: doc comment // 2.cue: file comment 1 // 2.cue: file comment 2 // 2.cue: d d: 1 di: 1 dii: 1 -- 3.cue -- // 3.cue: pkg doc comment package t // 3.cue: pkg comment 1 // 3.cue: d comment d: 1 di: 1 dii: 1 -- 4.cue -- // 4.cue: doc comment // 4.cue: file comment 1 // 4.cue: file comment 2 // 4.cue: d d: 1 di: 1 dii: 1 -- stdout-1.cue -- // 1.cue: file comment // 1.cue: pkg doc comment package t // 1.cue: pkg comment 1 // 1.cue: pkg comment 2 // 1.cue: d comment d: 1 di: 1 dii: 1 -- stdout-2.cue -- // 2.cue: doc comment // 2.cue: file comment 1 // 2.cue: file comment 2 // 2.cue: d d: 1 di: 1 dii: 1 -- stdout-2-pkg.cue -- // 2.cue: file comment 1 // 2.cue: file comment 2 // 2.cue: doc comment package t // 2.cue: d d: 1 di: 1 dii: 1 -- stdout-3.cue -- -- stdout-1_2.cue -- // 1.cue: file comment // 2.cue: file comment 1 // 2.cue: file comment 2 // 1.cue: pkg doc comment // // 2.cue: doc comment package t // 1.cue: pkg comment 1 // 1.cue: pkg comment 2 // 1.cue: d comment // 2.cue: d d: 1 di: 1 dii: 1 -- stdout-2_1.cue -- // 1.cue: file comment // 2.cue: file comment 1 // 2.cue: file comment 2 // 1.cue: pkg doc comment // // 2.cue: doc comment package t // 1.cue: pkg comment 1 // 1.cue: pkg comment 2 // 1.cue: d comment // 2.cue: d d: 1 di: 1 dii: 1 -- stdout-1_3.cue -- // 1.cue: file comment // 1.cue: pkg doc comment // // 3.cue: pkg doc comment package t // 1.cue: pkg comment 1 // 1.cue: pkg comment 2 // 3.cue: pkg comment 1 // 1.cue: d comment // 3.cue: d comment d: 1 di: 1 dii: 1 -- stdout-3_1.cue -- // 1.cue: file comment // 1.cue: pkg doc comment // // 3.cue: pkg doc comment package t // 1.cue: pkg comment 1 // 1.cue: pkg comment 2 // 3.cue: pkg comment 1 // 1.cue: d comment // 3.cue: d comment d: 1 di: 1 dii: 1 -- stdout-2_4.cue -- // 2.cue: doc comment // // 4.cue: doc comment // 2.cue: file comment 1 // 2.cue: file comment 2 // 4.cue: file comment 1 // 4.cue: file comment 2 // 2.cue: d // 4.cue: d d: 1 di: 1 dii: 1 -- stdout-2_4-pkg.cue -- // 2.cue: file comment 1 // 2.cue: file comment 2 // 4.cue: file comment 1 // 4.cue: file comment 2 // 2.cue: doc comment // // 4.cue: doc comment package t // 2.cue: d // 4.cue: d d: 1 di: 1 dii: 1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_force.txtar000066400000000000000000000006721474664451600247040ustar00rootroot00000000000000# Verify that def with --force works # First time should simply succeed exec cue def -o test.cue file.cue cmp test.cue file.cue # Second time will fail without --force ! exec cue def -o test.cue file.cue stderr 'error writing "test.cue": file already exists' # Second time with --force should succeed exec cue def --force -o test.cue file.cue cmp test.cue file.cue -- file.cue -- package hello #who: "World" message: "Hello \(#who)!" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_inline.txtar000066400000000000000000000011171474664451600250570ustar00rootroot00000000000000exec cue def cmp stdout out-stdout exec cue def --inline-imports cmp stdout out-stdout-expand -- cue.mod/module.cue -- module: "mod.test/a" language: version: "v0.9.0" -- in.cue -- package a import "mod.test/a/pkg" import "list" v: pkg.v // Never inline core packages. run: list.Comparer -- pkg/pkg.cue -- package pkg v: { x: 3, y: x } -- out-stdout -- package a import ( "mod.test/a/pkg" "list" ) v: pkg.v // Never inline core packages. run: list.Comparer -- out-stdout-expand -- package a import "list" v: { x: 3 y: x } // Never inline core packages. run: list.Comparer cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_issue2251.txtar000066400000000000000000000006311474664451600252430ustar00rootroot00000000000000# See also issue304.txtar exec cue def 1.cue --outfile 2.cue exec cue def 2.cue --outfile 3.cue exec cue def 3.cue cmp stdout golden1.output -- 1.cue -- import "example.com/repro/foo" foo.#Foo a: "A" -- foo/foo.cue -- package foo #Foo: { a: string } -- cue.mod/module.cue -- module: "example.com/repro" language: version: "v0.9.0" -- golden1.output -- import "example.com/repro/foo" foo.#Foo a: "A" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_issue3646.txtar000066400000000000000000000014011474664451600252500ustar00rootroot00000000000000env CUE_EXPERIMENT=evalv3=0 exec cue def --inline-imports ./p1 stdin stdout exec cue eval --out=json - cmp stdout stdout.golden env CUE_EXPERIMENT=evalv3=1 exec cue def --inline-imports ./p1 stdin stdout exec cue eval --out=json - cmp stdout stdout.golden -- go.mod -- module mod.example require cuelang.org/go v0.11.1 -- deps.go -- package deps import _ "cuelang.org/go/cmd/cue" -- cue.mod/module.cue -- module: "example.com/def" language: { version: "v0.9.2" } -- p1/caller.cue -- package p1 import ( "example.com/def/p2" ) r: "us-east-1" shortRegionName: p2.regionMap[r] -- p2/callee.cue -- package p2 #RegionMap: { "us-east-1": "ue1" "us-west_1": "uw1" } regionMap: #RegionMap -- stdout.golden -- { "r": "us-east-1", "shortRegionName": "ue1" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_jsonschema.txtar000066400000000000000000000051431474664451600257360ustar00rootroot00000000000000exec cue def jsonschema: schema.json -p schema -l '#Person:' cmp stdout expect-stdout # auto mode exec cue def schema.json -p schema -l '#Person:' cmp stdout expect-stdout exec cue def jsonschema: bad.json # The default strictness modes should apply even when # we haven't explicitly specifed the jsonschema file type. ! exec cue def jsonschema+strictFeatures: bad.json cmp stderr expect-stderr-strict-features exec cue def jsonschema: bad.json ! exec cue def jsonschema: bad.json --strict cmp stderr expect-stderr-strict ! exec cue def jsonschema+strict: bad.json cmp stderr expect-stderr-strict # With only strict features, it should error only for the # unimplemented feature and not for the unknown keyword. ! exec cue def jsonschema+strictFeatures: bad.json cmp stderr expect-stderr-strict-features ! exec cue export data.yaml schema.json cmp stderr expect-stderr2 ! exec cue vet data.yaml schema.json cmp stderr expect-stderr3 -- expect-stdout -- // Person package schema import "strings" #Person: { @jsonschema(schema="http://json-schema.org/draft-07/schema#") @jsonschema(id="https://example.com/person.schema.json") // The person's first name. firstName?: string // The person's last name. lastName?: strings.MinRunes(1) // Age in years which must be equal to or greater than zero. age?: int & >=0 ... } -- schema.json -- { "$id": "https://example.com/person.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "Person", "type": "object", "properties": { "firstName": { "type": "string", "description": "The person's first name." }, "lastName": { "type": "string", "description": "The person's last name.", "minLength": 1 }, "age": { "description": "Age in years which must be equal to or greater than zero.", "type": "integer", "minimum": 0 } } } -- bad.json -- { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "number", "$dynamicAnchor": "bar", "foo": true } -- expect-stderr-strict -- keyword "$dynamicAnchor" not yet implemented: ./bad.json:4:3 unknown keyword "foo": ./bad.json:5:3 -- expect-stderr-strict-features -- keyword "$dynamicAnchor" not yet implemented: ./bad.json:4:3 -- data.yaml -- age: twenty -- expect-stderr2 -- age: conflicting values "twenty" and int (mismatched types string and int): ./data.yaml:1:6 ./schema.json:18:7 -- expect-stderr3 -- age: conflicting values "twenty" and int (mismatched types string and int): ./data.yaml:1:6 ./schema.json:18:7 -- cue.mod/module.cue -- module: "mod.test/config" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_openapi.txtar000066400000000000000000000126161474664451600252420ustar00rootroot00000000000000exec cue def foo.cue -o openapi+cue:out.cue cmp out.cue expect-out.cue exec cue def openapi+cue: expect-cue-out -o - exec cue def foo.cue -o openapi:- cmp stdout expect-json-out exec cue def foo.cue -o openapi+cue:- cmp stdout expect-cue-out exec cue def foo.cue -o openapi+yaml:- cmp stdout expect-yaml-out exec cue def -p foo openapi: openapi.json cmp stdout expect-cue # auto mode exec cue def -p foo openapi.json cmp stdout expect-cue # cue to openapi exec cue def openapi+cue: expect-cue-out -o - cmp stdout expect-cue2 # combine exec cue def -p foo openapi.json openapi2.json cmp stdout expect-cue3 -- foo.cue -- // Some clever title. $version: "v1" #Foo: { a: int b: uint & <10 } #Bar: { foo: #Foo } -- openapi.json -- { "openapi": "3.0.0", "info": { "title": "My OpenAPI", "version": "v1alpha1" }, "paths": {}, "components": { "schemas": { "Bar": { "type": "object", "required": [ "foo" ], "x-ignored": "something", "properties": { "foo": { "$ref": "#/components/schemas/Foo" } } }, "Foo": { "type": "object", "required": [ "a", "b" ], "properties": { "a": { "type": "integer" }, "b": { "type": "integer", "minimum": 0, "exclusiveMaximum": 10 } } } } } } -- openapi2.json -- { "openapi": "3.0.0", "info": { "title": "My OpenAPI2", "version": "v1alpha1" }, "paths": {}, "components": { "schemas": { "Baz": { "type": "object", "required": [ "a", "b" ], "properties": { "a": { "type": "integer" }, "b": { "type": "integer", "minimum": 0, "exclusiveMaximum": 10 } } } } } } -- expect-json-out -- { "openapi": "3.0.0", "info": { "title": "Some clever title.", "version": "v1" }, "paths": {}, "components": { "schemas": { "Bar": { "type": "object", "required": [ "foo" ], "properties": { "foo": { "$ref": "#/components/schemas/Foo" } } }, "Foo": { "type": "object", "required": [ "a", "b" ], "properties": { "a": { "type": "integer" }, "b": { "type": "integer", "minimum": 0, "maximum": 10, "exclusiveMaximum": true } } } } } } -- expect-yaml-out -- openapi: 3.0.0 info: title: Some clever title. version: v1 paths: {} components: schemas: Bar: type: object required: - foo properties: foo: $ref: '#/components/schemas/Foo' Foo: type: object required: - a - b properties: a: type: integer b: type: integer minimum: 0 maximum: 10 exclusiveMaximum: true -- expect-cue-out -- openapi: "3.0.0" info: { title: "Some clever title." version: "v1" } paths: {} components: schemas: { Bar: { type: "object" required: ["foo"] properties: foo: $ref: "#/components/schemas/Foo" } Foo: { type: "object" required: ["a", "b"] properties: { a: type: "integer" b: { type: "integer" minimum: 0 maximum: 10 exclusiveMaximum: true } } } } -- expect-cue -- // My OpenAPI package foo info: { title: *"My OpenAPI" | string version: *"v1alpha1" | string } #Bar: { foo!: #Foo ... } #Foo: { a!: int b!: uint & <10 ... } -- expect-cue2 -- info: { title: *"Some clever title." | string version: *"v1" | string } #Bar: { foo!: #Foo ... } #Foo: { a!: int b!: uint & <10 ... } -- expect-cue3 -- // My OpenAPI // // My OpenAPI2 package foo info: { title: (*"My OpenAPI" | string) & (*"My OpenAPI2" | string) version: (*"v1alpha1" | string) & (*"v1alpha1" | string) } #Bar: { foo!: #Foo ... } #Foo: { a!: int b!: uint & <10 ... } #Baz: { a!: int b!: uint & <10 ... } -- expect-out.cue -- openapi: "3.0.0" info: { title: "Some clever title." version: "v1" } paths: {} components: schemas: { Bar: { type: "object" required: ["foo"] properties: foo: $ref: "#/components/schemas/Foo" } Foo: { type: "object" required: ["a", "b"] properties: { a: type: "integer" b: { type: "integer" minimum: 0 maximum: 10 exclusiveMaximum: true } } } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_openapi_nodoc.txtar000066400000000000000000000004211474664451600264130ustar00rootroot00000000000000# Make sure that `cue def` works when the OpenAPI # schema does not have a top level doc field. exec cue def openapi+yaml: schema.yaml cmp stdout want.cue -- schema.yaml -- openapi: "3.0.0" components: schemas: Foo: type: string -- want.cue -- #Foo: string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_openapi_strict.txtar000066400000000000000000000044011474664451600266230ustar00rootroot00000000000000exec cue def openapi: openapi.json # Default is to best-effort mode. exec cue def openapi.json cmp stdout expect-out.cue # We can enable strictFeatures to give an error when # unimplemented features are used. ! exec cue def openapi+strictFeatures: openapi.json cmp stderr expect-stderr-1 # Bad keywords are still always bad with OpenAPI 3.0. ! exec cue def openapi-badkeyword.json cmp stderr expect-stderr-2 ! exec cue def openapi+strictKeywords=0: openapi-badkeyword.json cmp stderr expect-stderr-2 # Keywords should be less strict in OpenAPI 3.1, because # it mirrors JSON Schema. exec cue def openapi3.1-badkeyword.json # We can enable strict keyword checking similarly # to jsonschema, with either strict or strictKeywords: ! exec cue def openapi+strictKeywords: openapi3.1-badkeyword.json cmp stderr expect-stderr-3 ! exec cue def openapi+strict: openapi3.1-badkeyword.json cmp stderr expect-stderr-3 -- openapi.json -- { "openapi": "3.0.0", "info": { "title": "My OpenAPI", "version": "v1alpha1" }, "paths": {}, "components": { "schemas": { "Bar": { "type": "object", "x-foo": "always allowed", "xml": "maybe we will never implement this" } } } } -- openapi-badkeyword.json -- { "openapi": "3.0.0", "info": { "title": "My OpenAPI", "version": "v1alpha1" }, "paths": {}, "components": { "schemas": { "Bar": { "type": "object", "unknown": "never OK" } } } } -- openapi3.1-badkeyword.json -- { "openapi": "3.1.0", "info": { "title": "My OpenAPI", "version": "v1alpha1" }, "paths": {}, "components": { "schemas": { "Bar": { "type": "object", "unknown": "usually OK" } } } } -- expect-stderr-1 -- keyword "xml" not yet implemented: ./openapi.json:13:17 -- expect-out.cue -- info: { title: *"My OpenAPI" | string version: *"v1alpha1" | string } #Bar: { ... } -- expect-stderr-2 -- unknown keyword "unknown": ./openapi-badkeyword.json:12:17 -- expect-stderr-3 -- unknown keyword "unknown": ./openapi3.1-badkeyword.json:12:17 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_package.txtar000066400000000000000000000006631474664451600252010ustar00rootroot00000000000000# Ensure that cue def with a --package flag outputs CUE that belongs to a # package. # Regular cue def exec cue def -p blah x.cue cmp stdout orig.golden # Self-contained exec cue def -p blah -e x x.cue cmp stdout self_contained.golden -- x.cue -- #Def: int x: #Def & 5 -- orig.golden -- package blah #Def: int x: #Def & { 5 } -- self_contained.golden -- package blah DEF.#x & { 5 } //cue:path: #Def let DEF = { #x: int } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/def_proto.txtar000066400000000000000000000200531474664451600247440ustar00rootroot00000000000000exec cue def policy.proto -p api -I include cmp stdout expect-stdout -- expect-stdout -- package api import "time" // Attributes defines attributes. #Attributes: { // A map of attribute name to its value. attributes?: { [string]: #AttributeValue } @protobuf(1,map[string]AttributeValue) // Specifies one attribute value with different type. #AttributeValue: {} | { stringValue: string @protobuf(2,string,name=string_value) } | { int64Value: int64 @protobuf(3,int64,name=int64_value) } | { doubleValue: float64 @protobuf(4,double,name=double_value) } | { boolValue: bool @protobuf(5,bool,name=bool_value) } | { bytesValue: bytes @protobuf(6,bytes,name=bytes_value) } | { timestampValue: time.Time @protobuf(7,google.protobuf.Timestamp,name=timestamp_value) } | { // Used for values of type STRING_MAP stringMapValue: #StringMap @protobuf(9,StringMap,name=string_map_value) } // Defines a string map. #StringMap: { // Holds a set of name/value pairs. entries?: { [string]: string } @protobuf(1,map[string]string) } } -- policy.proto -- syntax = "proto3"; import "google/protobuf/timestamp.proto"; package acme.api.v1; option go_package = "mod.test/api/v1"; // Attributes defines attributes. message Attributes { // A map of attribute name to its value. map attributes = 1; // Specifies one attribute value with different type. message AttributeValue { // The attribute value. oneof value { string string_value = 2; int64 int64_value = 3; double double_value = 4; bool bool_value = 5; bytes bytes_value = 6; google.protobuf.Timestamp timestamp_value = 7; // Used for values of type STRING_MAP StringMap string_map_value = 9; } } // Defines a string map. message StringMap { // Holds a set of name/value pairs. map entries = 1; } } -- include/google/protobuf/timestamp.proto -- // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; option go_package = "github.com/golang/protobuf/ptypes/timestamp"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; // A Timestamp represents a point in time independent of any time zone or local // calendar, encoded as a count of seconds and fractions of seconds at // nanosecond resolution. The count is relative to an epoch at UTC midnight on // January 1, 1970, in the proleptic Gregorian calendar which extends the // Gregorian calendar backwards to year one. // // All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap // second table is needed for interpretation, using a [24-hour linear // smear](https://developers.google.com/time/smear). // // The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By // restricting to that range, we ensure that we can convert to and from [RFC // 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. // // # Examples // // Example 1: Compute Timestamp from POSIX `time()`. // // Timestamp timestamp; // timestamp.set_seconds(time(NULL)); // timestamp.set_nanos(0); // // Example 2: Compute Timestamp from POSIX `gettimeofday()`. // // struct timeval tv; // gettimeofday(&tv, NULL); // // Timestamp timestamp; // timestamp.set_seconds(tv.tv_sec); // timestamp.set_nanos(tv.tv_usec * 1000); // // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. // // FILETIME ft; // GetSystemTimeAsFileTime(&ft); // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; // // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. // Timestamp timestamp; // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); // // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. // // long millis = System.currentTimeMillis(); // // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) // .setNanos((int) ((millis % 1000) * 1000000)).build(); // // // Example 5: Compute Timestamp from current time in Python. // // timestamp = Timestamp() // timestamp.GetCurrentTime() // // # JSON Mapping // // In JSON format, the Timestamp type is encoded as a string in the // [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the // format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" // where {year} is always expressed using four digits while {month}, {day}, // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone // is required. A proto3 JSON serializer should always use UTC (as indicated by // "Z") when printing the Timestamp type and a proto3 JSON parser should be // able to accept both UTC and other timezones (as indicated by an offset). // // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past // 01:30 UTC on January 15, 2017. // // In JavaScript, one can convert a Date object to this format using the // standard // [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) // method. In Python, a standard `datetime.datetime` object can be converted // to this format using // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use // the Joda Time's [`ISODateTimeFormat.dateTime()`]( // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D // ) to obtain a formatter capable of generating timestamps in this format. // // message Timestamp { // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. int64 seconds = 1; // Non-negative fractions of a second at nanosecond resolution. Negative // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. int32 nanos = 2; } -- cue.mod/module.cue -- module: "mod.test/config" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/dev.txtar000066400000000000000000000007101474664451600235370ustar00rootroot00000000000000env CUE_EXPERIMENT=evalv3=0 ! exec cue eval cmp stderr outv2 env CUE_EXPERIMENT=evalv3 exec cue eval cmp stdout outv3 -- test.cue -- package foo // This only works in the new evaluator as of this writing. y: 1 | {y: 1} y -- outv3 -- y: 1 -- outv2 -- 2 errors in empty disjunction: conflicting values 1 and {y:(1|{y:1}),y} (mismatched types int and struct): ./test.cue:1:1 ./test.cue:4:4 cannot add field y: was already used: ./test.cue:4:9 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/dotfile.txtar000066400000000000000000000001701474664451600244070ustar00rootroot00000000000000exec cue export ./.foo cmp stdout stdout.golden -- .foo/x.cue -- package foo x: 1 -- stdout.golden -- { "x": 1 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/embed.txtar000066400000000000000000000122631474664451600240430ustar00rootroot00000000000000# Embedding is enabled by default, but it can still be disabled. env CUE_EXPERIMENT=embed=0 ! exec cue eval cmp stderr out/noembed env CUE_EXPERIMENT= exec cue eval cmp stdout out/eval exec cue export --out cue cmp stdout out/export exec cue vet cmp stdout out/vet exec cue cmd test cmp stdout out/cmd -- cue.mod/module.cue -- module: "cue.example" language: version: "v0.11.0" -- test.cue -- @extern(embed) package foo a: _ @embed(file="test.json") b: _ @embed(file="input.yaml") c: _ @embed(file="test.json", type=text) d: _ @embed(glob="y/*", type=yaml) d: _ @embed(glob="x/*.yaml") // merge into the same map f: _ @embed(file="openapi.json", type=openapi) g: _ @embed(file="openapi.json") // test no auto mode! special: { // These are all valid. underscoreFile: _ @embed(file="y/_test.json") dotFile: _ @embed(file="y/.test.json") dotdotFile: _ @embed(file="..dotdot.json") underscoreDir: _ @embed(file="_y/test.json") dotDir: _ @embed(file=".y/test.json") } -- foo_tool.cue -- @extern(embed) package foo import ( "strings" "tool/cli" ) embedded_toolfile: _ @embed(file="input.yaml", type=text) command: test: { regularFile: cli.Print & { text: "from foo.cue: \(strings.TrimSpace(c))" } toolFile: cli.Print & { $after: regularFile // for consistent output text: "from foo_tool.cue: \(strings.TrimSpace(embedded_toolfile))" } } -- test.json -- { "x": 34 } -- input.yaml -- a1: 2 -- ..dotdot.json -- {"dotdot": true} -- y/test.json -- { "x": 34 } -- y/_test.json -- { "z": 45 } -- y/.test.json -- { "z": 46 } -- _y/test.json -- { "z": 47 } -- .y/test.json -- { "z": 48 } -- y/subdir/another.json -- { "z": 49 } -- _z/test.json -- -- x/input.yaml -- a1: 2 -- a/b/cue.mod/modules.cue -- module: "acme.com" language: version: "v0.9.0" -- a/b/foo.json -- {"a": 1, "b": 2} -- openapi.json -- { "openapi": "3.0.0", "info": { "title": "My OpenAPI", "version": "v1alpha1" }, "paths": {}, "components": { "schemas": { "Bar": { "type": "object", "required": [ "foo" ], "properties": { "foo": { "$ref": "#/components/schemas/Foo" } } }, "Foo": { "type": "object", "required": [ "a", "b" ], "properties": { "a": { "type": "integer" }, "b": { "type": "integer", "minimum": 0, "exclusiveMaximum": 10 } } } } } } -- out/noembed -- no interpreter defined for "embed": ./test.cue:1:1 -- out/eval -- a: { x: 34 } b: { a1: 2 } c: """ { "x": 34 } """ d: { "x/input.yaml": { a1: 2 } "y/_test.json": { z: 45 } "y/test.json": { x: 34 } } f: { info: { title: "My OpenAPI" version: "v1alpha1" } #Bar: { foo!: { a!: int b!: uint & <10 } } #Foo: { a!: int b!: uint & <10 } } g: { openapi: "3.0.0" info: { title: "My OpenAPI" version: "v1alpha1" } paths: {} components: { schemas: { Bar: { type: "object" required: ["foo"] properties: { foo: { $ref: "#/components/schemas/Foo" } } } Foo: { type: "object" required: ["a", "b"] properties: { a: { type: "integer" } b: { type: "integer" minimum: 0 exclusiveMaximum: 10 } } } } } } special: { underscoreFile: { z: 45 } dotFile: { z: 46 } dotdotFile: { dotdot: true } underscoreDir: { z: 47 } dotDir: { z: 48 } } -- out/export -- a: x: 34 b: a1: 2 c: """ { "x": 34 } """ d: { "x/input.yaml": a1: 2 "y/_test.json": z: 45 "y/test.json": x: 34 } f: info: { title: "My OpenAPI" version: "v1alpha1" } g: { openapi: "3.0.0" info: { title: "My OpenAPI" version: "v1alpha1" } paths: {} components: schemas: { Bar: { type: "object" required: ["foo"] properties: foo: $ref: "#/components/schemas/Foo" } Foo: { type: "object" required: ["a", "b"] properties: { a: type: "integer" b: { type: "integer" minimum: 0 exclusiveMaximum: 10 } } } } } special: { // These are all valid. underscoreFile: z: 45 dotFile: z: 46 dotdotFile: dotdot: true underscoreDir: z: 47 dotDir: z: 48 } -- out/vet -- -- out/cmd -- from foo.cue: { "x": 34 } from foo_tool.cue: a1: 2 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/embed_err.txtar000066400000000000000000000123641474664451600247150ustar00rootroot00000000000000! exec cue eval ! stdout . cmp stderr out/err # On systems with symlink support, we follow symlinks when embedding files. # TODO: add a test case for a symlink pointing to a file # outside of the current module, as that should likely be forbidden. [!symlink] stop cd symlink symlink symlink.json -> test.json symlink symlink-parent.json -> ../test.json symlink symlink-dir -> y exec cue eval . cmp stdout out/std -- cue.mod/module.cue -- module: "cue.example" language: version: "v0.11.0" -- test.cue -- @extern(embed) package foo none: _@embed(type=foo) both: _ @embed(file=test.json, glob="x/*.*", type=yaml) dotdot: _ @embed(file="../test.json") abs: _ @embed(file=/input.yaml) nonexist: _ @embed(file=y/test.json, type=text) dir: _ @embed(glob="x", type=yaml) dirslash: _ @embed(glob="x/", type=yaml) dotdotglob: _ @embed(glob="../test.json", type=yaml) absglob: _ @embed(glob="/x/*.*", type=yaml) doublestar: _ @embed(glob="**/*.json") stream: _ @embed(file=test.ndjson) singlestream: _ @embed(file=single.ndjson) yamlstream: _ @embed(file=stream.yaml) textproto: _ @embed(file=test.textproto) norm1: _ @embed(file=./test.json) norm2: _ @embed(file="x/../test.json") norm3: _ @embed(file="x/../x/test.json") norm4: _ @embed(file="x//test.json") noTranslateBS: _ @embed(file="x\\test.json") autoCUEfiletype: _ @embed(file="x.cue") explicitCUEfiletype: _ @embed(file=xcue, type=cue) // intentional missing type arg unspecifiedFiletype1: _ @embed(glob=x/*.*) unspecifiedFiletype2: _ @embed(glob=x/*) unspecifiedFiletype3: _ @embed(glob=x/*.?son) unspecifiedFiletype4: _ @embed(glob=x/*.[j]son) nestedModJSON: _ @embed(file="a/b/foo.json") nestedModJSONWithGlob: _ @embed(glob="a/*/*.json") directory: _ @embed(file="x", type=cue) buildFailure: _ @embed(file="buildfail.cue") invalidFiletype: _ @embed(file="x.unknown") invalidPattern: _ @embed(glob="x[") -- test.json -- { "x": 34 } -- test.ndjson -- { "x": 35 } { "x": 36 } -- single.ndjson -- { "x": 37 } -- stream.yaml -- 1 --- 2 -- input.yaml -- a1: 2 -- x/test.json -- { "x": 34 } -- x/input.yaml -- a1: 2 -- test.textproto -- a: 1 -- x.cue -- x: 5 -- xcue -- x: 5 -- buildfail.cue -- x: 5 & >10 -- a/b/cue.mod/modules.cue -- module: "acme.com" language: version: "v0.9.0" -- a/b/foo.json -- {"a": 1, "b": 2} -- out/err -- @embed: attribute must have file or glob field: ./test.cue:5:8 @embed: attribute cannot have both file and glob field: ./test.cue:7:9 @embed: cannot refer to parent directory: ./test.cue:9:11 @embed: only relative files are allowed: ./test.cue:11:8 @embed: open y/test.json: no such file or directory: ./test.cue:13:13 @embed: path not normalized, use "x" instead: ./test.cue:17:13 @embed: cannot refer to parent directory: ./test.cue:19:15 @embed: only relative files are allowed: ./test.cue:21:12 @embed: invalid glob pattern "**/*.json": '**' is not supported in patterns as of yet: ./test.cue:23:15 @embed: streaming not implemented: found more than one value in file: ./test.cue:25:11 @embed: encoding "jsonl" not (yet) supported: requires support for streaming: ./test.cue:27:17 @embed: streaming not implemented: found more than one value in file: ./test.cue:29:15 @embed: encoding "textproto" not (yet) supported: requires support for schema-guided decoding: ./test.cue:31:14 @embed: path not normalized, use "test.json" instead: ./test.cue:33:10 @embed: path not normalized, use "test.json" instead: ./test.cue:35:10 @embed: path not normalized, use "x/test.json" instead: ./test.cue:37:10 @embed: path not normalized, use "x/test.json" instead: ./test.cue:39:10 @embed: open x\test.json: no such file or directory: ./test.cue:41:18 @embed: encoding "cue" not (yet) supported: ./test.cue:43:20 @embed: encoding "cue" not (yet) supported: ./test.cue:44:24 @embed: extension not fully specified; type argument required: ./test.cue:47:25 @embed: extension not fully specified; type argument required: ./test.cue:48:25 @embed: extension not fully specified; type argument required: ./test.cue:49:25 @embed: extension not fully specified; type argument required: ./test.cue:50:25 @embed: cannot embed file "a/b/foo.json": in different module: ./test.cue:52:18 @embed: cannot embed file "a/b/foo.json": in different module: ./test.cue:53:26 @embed: cannot embed directories: ./test.cue:55:14 @embed: encoding "cue" not (yet) supported: ./test.cue:57:17 @embed: unknown file extension .unknown: ./test.cue:59:20 @embed: invalid glob pattern "x[": syntax error in pattern: ./test.cue:60:19 -- symlink/test.cue -- @extern(embed) package symlink file: _ @embed(file=symlink.json) glob: _ @embed(glob="*.json") fileSymlinkDir: _ @embed(file=symlink-dir/test.json) globSymlinkDir: _ @embed(glob="symlink-dir/*.json") -- symlink/test.json -- { "x": "symlink target file" } -- symlink/y/test.json -- { "y": "another symlink target file" } -- symlink/out/std -- file: { x: "symlink target file" } glob: { "symlink-parent.json": { x: 34 } "symlink.json": { x: "symlink target file" } "test.json": { x: "symlink target file" } } fileSymlinkDir: { y: "another symlink target file" } globSymlinkDir: { "symlink-dir/test.json": { y: "another symlink target file" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/embed_file_err.txtar000066400000000000000000000014401474664451600257050ustar00rootroot00000000000000# Test what happens when there is an error an embedded file. # The error should mention the name of the file where the error is. ! exec cue vet cmp stderr want-stderr ! exec cue export cmp stderr want-stderr ! exec cue def cmp stderr want-stderr -- want-stderr -- @embed: invalid string: ./x.cue:5:6 schema.json:10:7 -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.2" -- x.cue -- @extern(embed) package x e: _ @embed(glob="*.json",type=jsonschema) -- schema.json -- { "$schema": "http://json-schema.org/draft-04/schema#", "additionalProperties": false, "id": "https://example.test/example", "required": ["x"], "title": "example jsonschema", "type": "object", "properties": { "x": { "description": true, "type": "number" } } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/embed_mod.txtar000066400000000000000000000013021474664451600246720ustar00rootroot00000000000000exec cue mod tidy exec cue eval ./acme/foo cmp stdout out/eval -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- acme/foo/embed.cue -- @extern(embed) package foo import "example.com/e" a: _ @embed(file="test.json") b: _ @embed(file="x/test.json") c: e.a -- acme/foo/test.json -- { "x": 34 } -- acme/foo/x/test.json -- { "x": 35 } -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- @extern(embed) package e a: _ @embed(file=foo.txt) -- _registry/example.com_e_v0.0.1/foo.txt -- hello -- out/eval -- a: { x: 34 } b: { x: 35 } c: """ hello """ cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/embed_windows.txtar000066400000000000000000000021171474664451600256120ustar00rootroot00000000000000[!windows] cp reuse.json 'star/*.json' [!windows] exec cue export --out cue [!windows] cmp stdout out/export-unix [windows] exec cue export --out cue [windows] cmp stdout out/export-windows -- cue.mod/module.cue -- module: "cue.test" language: version: "v0.11.0" -- test.cue -- @extern(embed) package foo // Unix OSes can have a file containing a star character, and we can match it. // Windows can still use these file paths and glob patterns, but they can't match // a file containing a star character, as such filenames are not allowed on Windows. globStar: _ @embed(glob="star/*.json") globEscapeStar: _ @embed(glob="star/\\**", type=json) -- reuse.json -- {"x": "to be reused for more names"} -- star/simple.json -- {"x": "does not contain a star character"} -- out/export-unix -- globStar: { "star/*.json": x: "to be reused for more names" "star/simple.json": x: "does not contain a star character" } globEscapeStar: "star/*.json": x: "to be reused for more names" -- out/export-windows -- globStar: "star/simple.json": x: "does not contain a star character" globEscapeStar: {} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/encoding_comments.txtar000066400000000000000000000134711474664451600264640ustar00rootroot00000000000000# Test that the various encodings support encoding comments from CUE. # We cover multiple output modes (def, eval, export) as well as multiple encodings, # and also comments coming from definitions, unifications, and disjunctions. # Note that some encodings have no support for comments, like JSON. # This is meant mainly as an end-to-end smoke test; specific edge cases # should be tested in each encoding package. # TODO(mvdan): test importing comments into CUE as well. # TODO(mvdan): comments at the end of a file are not exported. # TODO(mvdan): comments at the start of a struct are not exported. # TODO(mvdan): comments attached to a list or its elements are not exported. # TODO(mvdan): comments between fields or list elements are not exported. exec cue def --out cue . cmp stdout def-cue.stdout # TODO(mvdan): why does eval not include comments when def and export do? exec cue eval --out cue . cmp stdout eval-cue.stdout exec cue export --out cue . cmp stdout export-cue.stdout exec cue export --out json . cmp stdout export-json.stdout # TODO(mvdan): YAML should support exporting comments. exec cue export --out yaml . cmp stdout export-yaml.stdout # TODO(mvdan): TOML should support exporting comments. exec cue export --out toml . cmp stdout export-toml.stdout -- basic.cue -- // comment at the start of a file. // Package p is an example package. package p // top-level comment before a simple field. foo: "bar" // top-level comment after a simple field. // top-level comment before a struct struct: { // comment at the start of a struct. // comment in a struct field field1: "message1" // comment between struct fields. field2: "message2" // comment at the end of a struct. } // top-level comment before a list. list: [ // comment at the start of a list. 1, // comment in a list element. 2, // comment between list elements. 3, // comment at the end of a list. ] // comment at the end of a file. -- schema.cue -- package p // Schema declares a schema. #Schema: { // name is the schema name. name?: string } -- data.cue -- package p // Data fits the schema. Data: #Schema & { // name is a specific name. name: "Foo" } // implicitUnified is any non-empty string. implicitUnified: string & != "" // implicitUnified is some string value. implicitUnified: "some value" // explicitUnified1 sets a default value. explicitUnified1: string | *"some default" // explicitUnified2 sets a value. explicitUnified2: "some value" // explicitUnified unifies two values. explicitUnified: explicitUnified1 & explicitUnified2 // disjunction1 has a default. _disjunction1: string | *"some default" // disjunction2 has no default. _disjunction2: int // disjunction is like a sum type. disjunction: _disjunction1 | _disjunction2 -- def-cue.stdout -- // comment at the start of a file. // Package p is an example package. package p // top-level comment before a simple field. foo: "bar" // top-level comment before a struct struct: { // comment in a struct field field1: "message1" field2: "message2" // comment at the end of a struct. } // Data fits the schema. Data: #Schema & { // name is a specific name. name: "Foo" } // Schema declares a schema. #Schema: { // name is the schema name. name?: string } // top-level comment before a list. list: [1, 2, 3] // implicitUnified is any non-empty string. // implicitUnified is some string value. implicitUnified: "some value" // explicitUnified1 sets a default value. explicitUnified1: string | *"some default" // explicitUnified2 sets a value. explicitUnified2: "some value" // explicitUnified unifies two values. explicitUnified: explicitUnified1 & explicitUnified2 // disjunction1 has a default. _disjunction1: string | *"some default" // disjunction2 has no default. _disjunction2: int // disjunction is like a sum type. disjunction: _disjunction1 | _disjunction2 -- eval-cue.stdout -- #Schema: {} Data: { name: "Foo" } foo: "bar" implicitUnified: "some value" explicitUnified1: "some default" explicitUnified2: "some value" explicitUnified: "some value" disjunction: "some default" struct: { field1: "message1" field2: "message2" } list: [1, 2, 3] -- export-cue.stdout -- // Data fits the schema. Data: { // name is the schema name. // name is a specific name. name: "Foo" } // top-level comment before a simple field. foo: "bar" // implicitUnified is any non-empty string. // implicitUnified is some string value. implicitUnified: "some value" // explicitUnified1 sets a default value. explicitUnified1: "some default" // explicitUnified2 sets a value. explicitUnified2: "some value" // explicitUnified unifies two values. explicitUnified: "some value" // disjunction is like a sum type. disjunction: "some default" // top-level comment before a struct struct: { // comment in a struct field field1: "message1" field2: "message2" // comment at the end of a struct. } // top-level comment before a list. list: [1, 2, 3] -- export-json.stdout -- { "Data": { "name": "Foo" }, "foo": "bar", "implicitUnified": "some value", "explicitUnified1": "some default", "explicitUnified2": "some value", "explicitUnified": "some value", "disjunction": "some default", "struct": { "field1": "message1", "field2": "message2" }, "list": [ 1, 2, 3 ] } -- export-yaml.stdout -- Data: name: Foo foo: bar implicitUnified: some value explicitUnified1: some default explicitUnified2: some value explicitUnified: some value disjunction: some default struct: field1: message1 field2: message2 list: - 1 - 2 - 3 -- export-toml.stdout -- disjunction = 'some default' explicitUnified = 'some value' explicitUnified1 = 'some default' explicitUnified2 = 'some value' foo = 'bar' implicitUnified = 'some value' list = [1, 2, 3] [Data] name = 'Foo' [struct] field1 = 'message1' field2 = 'message2' cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/encoding_empty.txtar000066400000000000000000000036141474664451600257730ustar00rootroot00000000000000# Test that the various encodings cope with empty files correctly. # Note that empty files or inputs have different meanings per encoding. # For example, in CUE and TOML they mean an empty struct or object, # in JSON they are invalid, and in JSONL they are a stream of zero values. # TODO(mvdan): cover more encodings: jsonschema, openapi, textproto, proto. # TODO(mvdan): json decoder errors seem to use absolute file paths, # which show the random directory names for each test run, # meaning that we can't cmp with a txtar file below. exec cue export cue: empty cmp stdout as-cue.stdout ! exec cue export json: empty stderr 'unexpected end of JSON input' exec cue export jsonl: empty cmp stdout as-jsonl.stdout exec cue export yaml: empty cmp stdout as-yaml.stdout exec cue export toml: empty cmp stdout as-toml.stdout # Also test inputs which are just whitespace, like newlines. exec cue export cue: newlines cmp stdout as-cue.stdout ! exec cue export json: newlines stderr 'unexpected end of JSON input' exec cue export jsonl: newlines cmp stdout as-jsonl.stdout exec cue export yaml: newlines cmp stdout as-yaml.stdout exec cue export toml: newlines cmp stdout as-toml.stdout # Also test inputs which are just comments. # Note that some languages support different syntaxes, or no comments at all. exec cue export cue: slash-comments cmp stdout as-cue.stdout ! exec cue export json: slash-comments stderr 'invalid character ./. looking for beginning of value' ! exec cue export jsonl: slash-comments stderr 'invalid character ./. looking for beginning of value' exec cue export yaml: hash-comments cmp stdout as-yaml.stdout exec cue export toml: hash-comments cmp stdout as-toml.stdout -- as-cue.stdout -- {} -- as-jsonl.stdout -- -- as-yaml.stdout -- null -- as-toml.stdout -- {} -- empty -- -- newlines -- -- slash-comments -- // Just two lines // of comments. -- hash-comments -- # Just two lines # of comments. cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/encoding_jsonl.txtar000066400000000000000000000037151474664451600257640ustar00rootroot00000000000000# JSONL is also known as NDJSON, and it used to be known as LDJSON too. # We support all three names as extensions. exec cue export input-jsonl.jsonl cmp stdout export.stdout exec cue export jsonl: input-none.none cmp stdout export.stdout exec cue export input-ndjson.ndjson cmp stdout export.stdout # TODO(mvdan): should we support ndjson as an alias for jsonl? it has become the more popular name. ! exec cue export ndjson: input-none.none stderr 'unknown filetype ndjson' exec cue export input-ldjson.ldjson cmp stdout export.stdout ! exec cue export ldjson: input-none.none stderr 'unknown filetype ldjson' # Multiple JSON values are rejected on a regular JSON file. ! exec cue export input-many.json stderr 'invalid JSON .* after top-level value' ! exec cue export json: input-none.none stderr 'invalid JSON .* after top-level value' exec cue export input-one.json cmp stdout export-one.stdout # Check that `cue import` supports all filenames too, # both by default and when loading JSON only. ! exec cue import --list --dry-run . stderr 'invalid JSON .*input-many.json.* after top-level value' rm input-many.json exec cue import --list --dry-run . cmp stderr import.stderr exec cue import json --list --dry-run . cmp stderr import.stderr -- input-none.none -- {"a": "one"} {"b": "two"} {"c1": "three", "c2": "four"} -- input-jsonl.jsonl -- {"a": "one"} {"b": "two"} {"c1": "three", "c2": "four"} -- input-ndjson.ndjson -- {"a": "one"} {"b": "two"} {"c1": "three", "c2": "four"} -- input-ldjson.ldjson -- {"a": "one"} {"b": "two"} {"c1": "three", "c2": "four"} -- export.stdout -- { "a": "one", "b": "two", "c1": "three", "c2": "four" } -- input-one.json -- {"a": "json one"} -- export-one.stdout -- { "a": "json one" } -- input-many.json -- {"a": "json one"} {"b": "json two"} {"c1": "json three", "c2": "json four"} -- import.stderr -- importing into input-jsonl.cue importing into input-ldjson.cue importing into input-ndjson.cue importing into input-one.cue cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/encoding_toml.txtar000066400000000000000000000014611474664451600256060ustar00rootroot00000000000000# Test that the TOML encoding is fully supported in cmd/cue. exec cue export --out toml . cmp stdout export.toml exec cue export --out json export.toml cmp stdout export.json exec cue import -o - export.toml cmp stdout import.cue exec cue import -o - toml . cmp stdout import.cue -- export.toml -- message = 'Hello World!' [nested] a1 = 'one level' [nested.a2] b = 'two levels' -- export.json -- { "message": "Hello World!", "nested": { "a1": "one level", "a2": { "b": "two levels" } } } -- import.cue -- message: "Hello World!" nested: a1: "one level" nested: a2: b: "two levels" -- data.cue -- package hello _who: "World" -- hello.cue -- package hello message: "Hello \(_who)!" // who declared in data.cue nested: a1: "one level" nested: a2: b: "two levels" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_concrete.txtar000066400000000000000000000005331474664451600255750ustar00rootroot00000000000000exec cue eval -c -a cmp stdout eval_conc.cue exec cue eval --out yaml cmp stdout eval_conc.yaml -- eval_conc.cue -- message: "Hello World!" -- eval_conc.yaml -- message: Hello World! -- cmd_echo.out -- Hello World! -- data.cue -- package hello #who: "World" -- hello.cue -- package hello message: "Hello \(#who)!" // who declared in data.cue cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_context.txtar000066400000000000000000000011571474664451600254620ustar00rootroot00000000000000exec cue eval --with-context -l '"\(path.Ext(filename)):\(index+1)/\(recordCount)"' -l 'data["@name"]' -s services.jsonl cmp stdout expect-stdout -- expect-stdout -- ".jsonl:1/3": elem1: { kind: "Service" "@name": "elem1" } ".jsonl:2/3": elem2: { kind: "Deployment" "@name": "elem2" } ".jsonl:3/3": elem3: { kind: "Service" "@name": "elem3" } -- services.jsonl -- { "kind": "Service", "@name": "elem1" } { "kind": "Deployment", "@name": "elem2" } { "kind": "Service", "@name": "elem3" } -- cue.mod/module.cue -- module: "mod.test/config" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_datapkg.txtar000066400000000000000000000013531474664451600254070ustar00rootroot00000000000000#Issue: 1596 exec cue eval . instance.json cmp stdout expect-stdout-eval exec cue def . instance.json cmp stdout expect-stdout-def exec cue vet . instance.json -- cue.mod/module.cue -- module: "mod.test/config" language: version: "v0.9.0" -- components/widget.cue -- package widget #Widget: { model: string explicit: "literal string" } -- config.cue -- package config import ( "mod.test/config/components:widget" ) w: widget.#Widget -- instance.json -- { "w": { "model": "retroencabulator" } } -- expect-stdout-eval -- w: { model: "retroencabulator" explicit: "literal string" } -- expect-stdout-def -- import "mod.test/config/components:widget" w: widget.#Widget & { model: "retroencabulator" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_e.txtar000066400000000000000000000021311474664451600242130ustar00rootroot00000000000000! exec cue eval -e nonExist cmp stderr expect/nonExist/stderr cmp stdout expect/nonExist/stdout # Issue #550: ignore incomplete error in different package exec cue eval -e incomplete cmp stderr expect/incomplete/stderr cmp stdout expect/incomplete/stdout # Issue #384 ! exec cue eval foo.bar cmp stderr expect/foobar/stderr # Issue #999 exec cue export --out text -e 'yaml.MarshalStream(X)' issue999/x.cue cmp stdout expect/issue999/stdout -- expect/nonExist/stdout -- -- expect/nonExist/stderr -- reference "nonExist" not found: --expression:1:1 -- expect/incomplete/stdout -- -- expect/incomplete/stderr -- -- expect/foobar/stdout -- -- expect/foobar/stderr -- unknown file extension .bar -- input/ -- -- partial.cue -- package exitcode import ( pkg "foo.com/example" ) a: 1 incomplete: pkg.Settings foo: bar: "hello" -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- cue.mod/pkg/foo.com/example/example.cue -- package example Settings: {} blah: Settings.anyKey -- issue999/x.cue -- X: [ { a: 1 }, { b: 2 }, ] -- expect/issue999/stdout -- a: 1 --- b: 2 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_e_hidden.txtar000066400000000000000000000003301474664451600255250ustar00rootroot00000000000000# Issue #904 exec cue eval -e _a stdout '34' exec cue eval -e _a dep.cue stdout '34' exec cue eval -e _a tst.cue stdout '34' exec cue eval -H stdout '_a: 34' -- dep.cue -- package dep _a: 34 -- tst.cue -- _a: 34cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_errs.txtar000066400000000000000000000012171474664451600247460ustar00rootroot00000000000000! exec cue eval errs.cue cmp stderr expect-stderr cmp stdout expect-stdout -- expect-stdout -- -- expect-stderr -- bar: 2 errors in empty disjunction: bar.a: conflicting values "str" and int (mismatched types string and int): ./errs.cue:5:10 ./errs.cue:6:6 ./errs.cue:6:16 bar.b: conflicting values 2 and string (mismatched types int and string): ./errs.cue:5:21 ./errs.cue:6:6 ./errs.cue:6:26 x.q: conflicting values "goodbye" and "hello": ./errs.cue:1:4 ./errs.cue:2:4 ./errs.cue:3:8 ./errs.cue:3:14 -- errs.cue -- a: "hello" b: "goodbye" x: {q: a, q: b} foo: {a: int} | {b: string} bar: foo & {a: "str", b: 2} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_expr.txtar000066400000000000000000000006351474664451600247540ustar00rootroot00000000000000! exec cue eval -c -e b.a.b -e b.idx cmp stderr expect-stderr cmp stdout expect-stdout -- expect-stdout -- // b.a.b 4 -- expect-stderr -- // b.idx b.idx: invalid non-ground value string (must be concrete string): ./partial.cue:8:7 -- partial.cue -- package partial def: *1 | int sum: 1 | 2 b: { idx: a[str] // should resolve to top-level `a` str: string } b: a: b: 4 a: { b: 3 c: 4 } c: b & {str: "b"} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_flags.txtar000066400000000000000000000021001474664451600250570ustar00rootroot00000000000000# Issue #969 ! exec cue eval test.json -n ".+\.cue" cmp stderr expect-stderr1 ! exec cue eval test.json -d '#D2' cmp stderr expect-stderr2 ! exec cue eval test.json -n ".+\.cue" -d '#D2' cmp stderr expect-stderr3 ! exec cue eval test.json vector.cue -d '#D1' cmp stderr expect-stderr4 ! exec cue eval test.json vector.cue -d '#D2' cmp stderr expect-stderr5 -- test.json -- { "X": 1, "Y": 2, "Z": 3 } -- vector.cue -- package Vector #D2: { X: float Y: float } #D3: { X: float Y: float Z: float } -- expect-stderr1 -- use of -n/--name flag without a directory -- expect-stderr2 -- -d/--schema flag specified without a schema -- expect-stderr3 -- use of -n/--name flag without a directory -- expect-stderr4 -- reference "#D1" not found: --schema:1:1 -- expect-stderr5 -- X: conflicting values 1 and float (mismatched types int and float): ./test.json:2:8 ./vector.cue:4:8 Y: conflicting values 2 and float (mismatched types int and float): ./test.json:3:8 ./vector.cue:5:8 Z: field not allowed: ./test.json:4:3 ./vector.cue:3:6 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_force.txtar000066400000000000000000000007771474664451600251030ustar00rootroot00000000000000# Verify that eval with --force works # First time should simply succeed exec cue eval -o eval.cue file.cue cmp eval.cue eval.golden # Second time will fail without --force ! exec cue eval -o eval.cue file.cue stderr 'error writing "eval.cue": file already exists' # Second time with --force should succeed exec cue eval --force -o eval.cue file.cue cmp eval.cue eval.golden -- file.cue -- package hello #who: "World" message: "Hello \(#who)!" -- eval.golden -- #who: "World" message: "Hello World!" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_hidden.txtar000066400000000000000000000007101474664451600252230ustar00rootroot00000000000000# File starting with . exec cue eval .foo.cue cmp stdout expect-stdout-dot # File starting with _ exec cue eval _foo.cue cmp stdout expect-stdout-underscore # Ensure package eval excludes both for completeness exec cue eval . cmp stdout expect-stdout-pkg -- .foo.cue -- package foo a: 42 -- _foo.cue -- package foo b: 42 -- foo.cue -- package foo c: 42 -- expect-stdout-dot -- a: 42 -- expect-stdout-underscore -- b: 42 -- expect-stdout-pkg -- c: 42 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_hiddenfail.txtar000066400000000000000000000007551474664451600260700ustar00rootroot00000000000000! exec cue eval cmp stderr expect-stderr # TODO(mvdan): note that removing cue.mod below makes the test fail, # as the filename in the error strings seems to be relative to the module root. # That should probably not be the case; it should be relative to the current directory. -- expect-stderr -- build constraints exclude all CUE files in .: .foo.cue: filename starts with a '.' -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- .foo.cue -- package foo a: 42 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_ignore.txtar000066400000000000000000000005201474664451600252520ustar00rootroot00000000000000exec cue eval -i in.cue cmp stdout expect/stdout # Issue #1981 # Issue #1786 -- in.cue -- a: 4 a: 5 l: [ 1, 2 ] l: [ 1, 3 ] list: [0, 1, 2] val: list[3] -- expect/stdout -- a: _|_ // a: conflicting values 5 and 4 l: [1, _|_, // l.1: conflicting values 3 and 2 ] list: [0, 1, 2] val: _|_ // val: index out of range [3] with length 3 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_import.txtar000066400000000000000000000002701474664451600253030ustar00rootroot00000000000000exec cue eval ./in.cue cmp stdout expect-stdout -- expect-stdout -- import "list" def: { #types: list.MinItems(1) } -- in.cue -- import ( "list" ) def: #types: list.MinItems(1) cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_issue3376.txtar000066400000000000000000000042341474664451600254500ustar00rootroot00000000000000# https://cuelang.org/issue/3376 # # The old evaluator does not correctly handle the difference in order of # declarations. To the extent that scenario2 gives an error: # # items.a: cannot add to field _: # ./scenario2.cue:1:32 # # and scenario4 results in a SIGSEV. # # The new evaluator correctly results in no errors in these cases. # evalv2 - scenario 1 exec cue eval ./scenario1.cue # evalv2 - scenario 2 # # This should not fail but it does. Fixed in evalv3 ! exec cue eval ./scenario2.cue cmp stderr scenario2.evalv2.stderr # evalv2 - scenario 3 exec cue eval ./scenario3.cue # evalv2 - scenario 4 # # This should not fail. Fixed in evalv3 ! exec cue eval ./scenario4.cue stderr 'items.a: cannot add to field ' env CUE_EXPERIMENT=evalv3 # evalv3 - scenario 1 exec cue eval ./scenario1.cue # evalv3 - scenario 2 exec cue eval ./scenario2.cue # evalv3 - scenario 3 exec cue eval ./scenario3.cue # evalv3 - scenario 4 exec cue eval ./scenario4.cue -- scenario1.cue -- #Item: { id!: string deps: [...or(known_ids)] | or(known_ids) } known_ids: [for k,v in items { v.id } ] items: [string]: #Item items: [Key=_]: { id: (Key) + "-id" } items: a: deps: items.b.id items: b: deps: [] items: c: deps: [items.a.id, items.b.id] -- scenario2.cue -- known_ids: [for k,v in items { v.id } ] #Item: { id!: string deps: [...or(known_ids)] | or(known_ids) } items: [string]: #Item items: [Key=_]: { id: (Key) + "-id" } items: a: deps: items.b.id items: b: deps: [] items: c: deps: [items.a.id, items.b.id] -- scenario3.cue -- #Item: { id!: string deps?: [...or(known_ids)] | or(known_ids) } known_ids: [for k,v in items { v.id } ] items: [string]: #Item items: [Key=_]: { id: (Key) + "-id" } items: a: deps: items.b.id items: b: deps: [] items: c: deps: [items.a.id, items.b.id] items: d: _ -- scenario4.cue -- known_ids: [for k,v in items { v.id } ] #Item: { id!: string deps?: [...or(known_ids)] | or(known_ids) } items: [string]: #Item items: [Key=_]: { id: (Key) + "-id" } items: a: deps: items.b.id items: b: deps: [] items: c: deps: [items.a.id, items.b.id] items: d: _ -- scenario2.evalv2.stderr -- items.a: cannot add to field _: ./scenario2.cue:1:32 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_loaderr.txtar000066400000000000000000000002461474664451600254240ustar00rootroot00000000000000! exec cue eval nonexisting . ! stdout . cmp stderr expect-stderr -- expect-stderr -- standard library import path "nonexisting" cannot be imported as a CUE package cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_mixedfiletypes.txtar000066400000000000000000000015161474664451600270300ustar00rootroot00000000000000#Issue 1479 exec cue eval x.cue data.json y.cue # Demonstrate checks are ok exec cue eval x.cue data.json cmp stdout stdout.golden # Import JSON and verify that we can assert checks are ok exec cue import data.json exec cue eval x.cue data.cue y.cue # Assert checks ok using CUE + JSON exec cue eval x.cue data.json y.cue -- data.json -- { "team": { "alice": [ "EM" ], "bob": [ "TL" ] } } -- x.cue -- import ( "list" ) #Team: [string]: [...("EM" | "IC" | "TL")] team: #Team checks: { enoughMembers: { ok: len(team) >= 1 } hasManager: { ok: len([for m in team if list.Contains(m, "EM") {m}]) >= 1 } } -- y.cue -- checks: [string]: ok: true -- stdout.golden -- #Team: {} team: { alice: ["EM"] bob: ["TL"] } checks: { enoughMembers: { ok: true } hasManager: { ok: true } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_newline.txtar000066400000000000000000000002611474664451600254320ustar00rootroot00000000000000exec cue eval ./data.cue cmp stdout expect-stdout exec cue eval ./data.cue -o out.cue cmp out.cue expect-out.cue -- data.cue -- 3 -- expect-stdout -- 3 -- expect-out.cue -- 3 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_notexistfatal.txtar000066400000000000000000000012021474664451600266520ustar00rootroot00000000000000#Issue: 1509 # TODO: recognize when an unresolved value # export ! exec cue export cmp stderr expect-stderr1 cmp stdout expect-stdout1 # eval exec cue eval cmp stderr expect-stderr2 cmp stdout expect-stdout2 -- x.cue -- package x import "list" x: [1, 2, 3] // This should be a fatal error, as the passed struct will never be // able to contain `less` by making the configuration more concrete. sortedx: list.Sort(x, {}) -- expect-stdout1 -- -- expect-stderr1 -- sortedx: error in call to list.Sort: field not found: less: ./x.cue:8:10 -- expect-stdout2 -- import "list" x: [1, 2, 3] sortedx: list.Sort(x, {}) -- expect-stderr2 -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_notexistincomplete.txtar000066400000000000000000000007401474664451600277300ustar00rootroot00000000000000#Issue: 1509 # export ! exec cue export cmp stderr expect-stderr1 cmp stdout expect-stdout1 # eval exec cue eval cmp stderr expect-stderr2 cmp stdout expect-stdout2 -- x.cue -- package x import "list" x: [1, 2, 3] sortedx: list.Sort(x, cmp) cmp: {} -- expect-stdout1 -- -- expect-stderr1 -- sortedx: error in call to list.Sort: field not found: less: ./x.cue:6:10 -- expect-stdout2 -- import "list" x: [1, 2, 3] sortedx: list.Sort(x, cmp) cmp: {} -- expect-stderr2 -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_rec.txtar000066400000000000000000000006211474664451600245420ustar00rootroot00000000000000exec cue eval ./rec.cue -O cmp stdout expect-stdout -- rec.cue -- Foo: { foo?: Foo bar: string baz: bar + "2" } foo: Foo & { foo: { bar: "barNested" } bar: "barParent" } -- expect-stdout -- Foo: { foo?: Foo bar: string baz: bar + "2" } foo: { foo: { foo?: Foo bar: "barNested" baz: "barNested2" } bar: "barParent" baz: "barParent2" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_resolve.txtar000066400000000000000000000023141474664451600254510ustar00rootroot00000000000000# Issue #736 # # references should never resolve to files of an # anonymous package (no package or package _). ! exec cue eval data.yaml check.cue cmp stderr out-stderr ! exec cue eval none.cue check.cue cmp stderr out-stderr ! exec cue eval anon.cue check.cue cmp stderr out-stderr # TODO: allow this for now. Files without a package clause should not resolve # across other files. exec cue eval package.cue check.cue -- data.yaml -- nodes: - name: foo childs: - bar - baz - name: bar parent: foo - name: baz parent: foo -- none.cue -- nodes: [{ name: "foo" childs: ["bar", "baz"] }, { name: "bar" parent: "foo" }, { name: "baz" parent: "foo" }] -- anon.cue -- // This is an explicitly declared anonymous package. package _ nodes: [{ name: "foo" childs: ["bar", "baz"] }, { name: "bar" parent: "foo" }, { name: "baz" parent: "foo" }] -- package.cue -- package list nodes: [{ name: "foo" childs: ["bar", "baz"] }, { name: "bar" parent: "foo" }, { name: "baz" parent: "foo" }] -- check.cue -- import "list" #map: {for n in nodes {"\(n.name)": n}} -- out-stderr -- #map: reference "nodes" not found: ./check.cue:3:17 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_stdin.txtar000066400000000000000000000002241474664451600251110ustar00rootroot00000000000000stdin stdin.cue exec cue eval t.cue - cmp stdout expect-stdout -- stdin.cue -- foo:3 -- t.cue -- foo: int bar: 3 -- expect-stdout -- foo: 3 bar: 3 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_tags.txtar000066400000000000000000000005231474664451600247300ustar00rootroot00000000000000exec cue eval -t env=staging -t name=bar cmp stdout expect-stdout -- expect-stdout -- var: { env: "staging" name: "bar" } -- tags.cue -- package tags var: env: "prod" | "staging" @tag(env,short=prod|staging) var: name: string @tag(name) // This is prohibited as for now. // foo: [string]: string @tag(all) // foo: bar: string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/eval_tool.txtar000066400000000000000000000003601474664451600247460ustar00rootroot00000000000000exec cue eval cmp stdout expect-stdout -- expect-stdout -- message: "Hello world!" -- task.cue -- package home message: "Hello world!" -- task_tool.cue -- package home command: run_list: runBase & { task: echo: cmd: ["echo", message] } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/exp_gengotypes.txtar000066400000000000000000000615511474664451600260330ustar00rootroot00000000000000exec cue exp gengotypes ./root ! stderr . # Check how many files were generated, and see that it aligns with how many files we expect. find-files . stdout -count=5 'cue_types_.*gen\.go$' stdout -count=5 'cue_types_.*gen\.go.want$' # No Go file is generated for imported itself, as it's only loaded as part of subpackage instances. ! stdout imported${/@R}gen_go.cue # No bad or unused packages should have been generated at all. ! stdout 'bad_.*'${/@R}gen_go.cue ! stdout 'unused.*'${/@R}gen_go.cue # Check the contents of the generated files. cmp root/cue_types_gen.go root/cue_types_gen.go cmp imported/subinst/cue_types_imported_gen.go imported/subinst/cue_types_imported_gen.go cmp imported/indirect/cue_types_gen.go imported/indirect/cue_types_gen.go cmp imported/multipkg/cue_types_multipkg_one_gen.go imported/multipkg/cue_types_multipkg_one_gen.go.want cmp imported/multipkg/cue_types_multipkg_two_gen.go imported/multipkg/cue_types_multipkg_two_gen.go.want # Check various properties about the generated code. # Names including "neverGenerate" signal that they must not be generated. ! grep '(?i)nevergenerate' root/cue_types_gen.go # Hidden definitions must never result in exported Go types. ! grep '^type Hidden' root/cue_types_gen.go # We use '_' as a separator for nested definitions; check it's not misused. ! grep '^type _' root/cue_types_gen.go ! grep '__' root/cue_types_gen.go # TODO: ensure that no IncompleteKind TODOs are left in the output. # The resulting Go should all build without error. go build ./... # Sanity check that our valid data tests validate against the schema with cmd/cue. exec cue vet -c cuetest/pass_check.cue cuetest/all.cue ! exec cue vet -c cuetest/fail_check.cue cuetest/all.cue cmp stderr cuetest/fail_check.stderr # The resulting Go should roundtrip with CUE correctly. # Extract the values from CUE in JSON for easy consumption. exec cue export cuetest/all.cue cp stdout gotest/all.json go run ./gotest # Check that the JSON values re-encoded from Go still validate with the CUE schema. exec cue vet -c -d '#root' ./root gotest/reencoded-pass.jsonl -- cue.mod/module.cue -- module: "foo.test/bar" language: version: "v0.11.0" -- cuetest/pass_check.cue -- package cuetest import "foo.test/bar/root" pass: [_]: root.#root -- cuetest/fail_check.cue -- package cuetest import "foo.test/bar/root" // Note that it would be nice to sanity check that all tests result in an error, // for example by using matchN or list.MatchN somehow. fail: [_]: [_]: root.#root fail: both: notString: "not_a_struct" -- cuetest/all.cue -- package cuetest pass: empty: {} fail: both: notString: "not_a_struct" fail: both: notList: [1, 2, 3] pass: noOptional: fields: {required: 3, regular: 4} pass: withOptional: fields: {required: 3, regular: 4, optional: 5} fail: cue: missingRequired: fields: regular: 4 fail: cue: isNotEqual: {mustEqual1: 8, mustEqual2: 99} pass: isEqual: {mustEqual1: 8, mustEqual2: 8} fail: cue: discBoth: discriminatorField: {one: 5, two: 5} pass: discOne: discriminatorField: one: 5 pass: discTwo: discriminatorField: two: 5 // To avoid repetition, we template the type test cases. // Note that some types have multipe test cases. for i, test in _typeTests { if test._fail == "none" { pass: "\(i)_\(test.name)": types: (test.name): test.pass } if test._fail == "cue" { fail: cue: "\(i)_\(test.name)": types: (test.name): test.fail.cue } if test._fail == "both" { fail: both: "\(i)_\(test.name)": types: (test.name): test.fail.both } } #typeTest: { name: string isPass: bool } #typeTest: { _fail: "none" pass!: _ } | { _fail: "cue" fail!: cue!: _ } | { _fail: "both" fail!: both!: _ } _typeTests: [...#typeTest] & [ // TODO: most failure tests below should also fail in Go. {name: "Null", pass: null}, {name: "Bool", pass: false}, {name: "Bool", pass: true}, {name: "Int", pass: 123}, {name: "Float", pass: 456.789}, {name: "String", pass: "foo bar"}, // {name: "Bytes", pass: '\x01\x02\x03'}, {name: "Number", pass: 12333}, {name: "Number", pass: 123.33}, {name: "Uint", pass: 123456789}, {name: "Uint", fail: cue: -34}, {name: "Int8", pass: 12}, {name: "Int8", fail: cue: 99999}, {name: "Int8", fail: cue: -99999}, {name: "Rune", pass: 140}, {name: "IntList", pass: [1, 2, 3]}, {name: "IntList", pass: []}, {name: "IntList", fail: both: ["foo", "bar"]}, {name: "IntListClosed2", pass: [1, 2]}, {name: "IntListClosed2", fail: cue: [1, 2, 3, 4]}, // too long {name: "IntMap", pass: {"one": 1, "two": 2}}, {name: "IntMap", fail: both: {"one": "x", "two": "y"}}, {name: "Time", pass: "1937-01-01T12:00:27.87+00:20"}, {name: "Duration", pass: "1h2m3s4ms"}, {name: "StringOrInt", pass: "foo"}, {name: "StringOrInt", pass: 345}, {name: "StringOrIntDefault", pass: "foo"}, {name: "StringOrIntDefault", pass: 345}, {name: "NullOrStruct", pass: null}, {name: "NullOrStruct", pass: {foo: 3}}, {name: "NullOrStruct", fail: cue: "foo"}, {name: "NullOrString", pass: null}, {name: "NullOrString", pass: "foo"}, {name: "NullOrString", fail: cue: 123}, {name: "NumericBounds", pass: 50}, {name: "NumericBounds", fail: cue: 5555}, {name: "NonEmptyString", pass: "foo"}, {name: "NonEmptyString", fail: cue: ""}, {name: "NonEmptyString", fail: both: 123}, {name: "UniqueStrings", pass: ["foo", "bar"]}, {name: "UniqueStrings", fail: cue: ["foo", "foo"]}, {name: "NonEmptyString", fail: both: [1, 2, 3]}, {name: "LinkedList", pass: {item: 12, next: {item: 34}}}, {name: "LinkedList", fail: both: {next: "x"}}, ] -- cuetest/fail_check.stderr -- fail.both."16_IntList".types.IntList.0: conflicting values "foo" and int (mismatched types string and int): ./cuetest/all.cue:67:40 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:26:20 ./root/types.cue:26:23 fail.both."16_IntList".types.IntList.1: conflicting values "bar" and int (mismatched types string and int): ./cuetest/all.cue:67:47 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:26:20 ./root/types.cue:26:23 fail.both."20_IntMap".types.IntMap.one: conflicting values "x" and int (mismatched types string and int): ./cuetest/all.cue:71:47 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:28:29 fail.both."20_IntMap".types.IntMap.two: conflicting values "y" and int (mismatched types string and int): ./cuetest/all.cue:71:59 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:28:29 fail.both."37_NonEmptyString".types.NonEmptyString: conflicting values string and 123 (mismatched types string and int): ./cuetest/all.cue:20:1 ./cuetest/all.cue:27:2 ./cuetest/all.cue:28:56 ./cuetest/all.cue:89:43 ./root/types.cue:38:23 fail.both."40_NonEmptyString".types.NonEmptyString: conflicting values string and [1,2,3] (mismatched types string and list): ./cuetest/all.cue:20:1 ./cuetest/all.cue:27:2 ./cuetest/all.cue:28:56 ./cuetest/all.cue:92:43 ./root/types.cue:38:23 fail.both."42_LinkedList".types.LinkedList.next: conflicting values "x" and {item?:_,next?:#linkedList} (mismatched types string and struct): ./cuetest/all.cue:94:50 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:40:23 ./root/types.cue:43:14 ./root/types.cue:45:9 fail.both.notList: conflicting values [1,2,3] and {doc?:_} (mismatched types list and struct): ./cuetest/all.cue:5:24 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:83:8 fail.both.notString: conflicting values "not_a_struct" and {doc?:_} (mismatched types string and struct): ./cuetest/all.cue:4:24 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:83:8 fail.cue."11_Int8".types.Int8: invalid value 99999 (out of bound <=127): ./cuetest/all.cue:61:30 fail.cue."12_Int8".types.Int8: invalid value -99999 (out of bound >=-128): ./cuetest/all.cue:62:30 fail.cue."18_IntListClosed2".types.IntListClosed2: incompatible list lengths (2 and 4) fail.cue."29_NullOrStruct".types.NullOrStruct: 2 errors in empty disjunction: fail.cue."29_NullOrStruct".types.NullOrStruct: conflicting values "foo" and null (mismatched types string and null): ./cuetest/all.cue:81:43 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:35:23 fail.cue."29_NullOrStruct".types.NullOrStruct: conflicting values "foo" and {foo?:int} (mismatched types string and struct): ./cuetest/all.cue:81:43 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:35:30 fail.cue."32_NullOrString".types.NullOrString: 2 errors in empty disjunction: fail.cue."32_NullOrString".types.NullOrString: conflicting values 123 and null (mismatched types int and null): ./cuetest/all.cue:84:43 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:36:23 fail.cue."32_NullOrString".types.NullOrString: conflicting values 123 and string (mismatched types int and string): ./cuetest/all.cue:84:43 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:12:10 ./root/types.cue:36:30 fail.cue."39_UniqueStrings".types.UniqueStrings: invalid value ["foo","foo"] (does not satisfy list.UniqueItems): equal value ("foo") at position 0 and 1: ./cuetest/all.cue:25:55 ./root/types.cue:39:23 fail.cue."9_Uint".types.Uint: invalid value -34 (out of bound >=0): ./cuetest/all.cue:59:30 fail.cue.discBoth.discriminatorField: 2 errors in empty disjunction: fail.cue.discBoth.discriminatorField.one: field not allowed: ./cuetest/all.cue:14:43 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:76:50 fail.cue.discBoth.discriminatorField.two: field not allowed: ./cuetest/all.cue:14:51 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:76:29 fail.cue.isNotEqual.mustEqual2: conflicting values 8 and 99: ./cuetest/all.cue:11:37 ./cuetest/all.cue:11:52 ./cuetest/fail_check.cue:7:12 ./cuetest/fail_check.cue:7:17 ./root/root.cue:79:15 fail.cue."34_NumericBounds".types.NumericBounds: invalid value 5555 (out of bound <100): ./root/types.cue:37:28 ./cuetest/all.cue:86:43 fail.cue."36_NonEmptyString".types.NonEmptyString: invalid value "" (out of bound !=""): ./root/types.cue:38:32 ./cuetest/all.cue:25:55 ./cuetest/all.cue:88:43 ./root/types.cue:38:23 -- go.mod -- module "foo.test/bar" go 1.22 -- gotest/gotest.go -- package main import ( "bytes" "encoding/json" "fmt" "go/constant" "go/token" "os" "reflect" "slices" "foo.test/bar/root" ) type Tests struct { Pass map[string]json.RawMessage Fail struct { CUE map[string]json.RawMessage Both map[string]json.RawMessage } } func main() { // Sanity check that some types and fields are what we expect them to be. var _ root.AttrChangedName var _ root.AttrChangedNameEmbed var _ = root.AttrType(constant.Kind(0)) // It's easier to test the fields with a root value. // We use reflection to ensure that inline struct pointers are initialized. var zeroRoot root.Root rv := reflect.ValueOf(&zeroRoot).Elem() fv := rv.FieldByName("Fields") fv.Set(reflect.New(fv.Type().Elem())) tv := rv.FieldByName("Types") tv.Set(reflect.New(tv.Type().Elem())) var _ = zeroRoot.Embedded1 var _ = zeroRoot.Embedded2 // TODO: embedded structs should remain // var _ = root.Root.EmbeddedStruct var _ = zeroRoot.AttrChangedName var _ = zeroRoot.AttrChangedNameNested zeroRoot.AttrType = constant.Kind(0) zeroRoot.AttrTypeCompat = token.Token(0) zeroRoot.AttrTypeNested = make(map[any]any) zeroRoot.DiscriminatorField = make(map[string]any) zeroRoot.Fields.OptionalStruct = &root.EmptyStruct{} zeroRoot.Fields.OptionalStructAttrType = root.EmptyStruct{} zeroRoot.Types.IntMap = make(map[string]int64) // Sanity check that Go can JSON decode all the values we expect. // We also re-encode the ones we expect CUE to be able to validate again. data := try1(os.ReadFile("gotest/all.json")) var tests Tests try(json.Unmarshal(data, &tests)) failed := false f := try1(os.Create("gotest/reencoded-pass.jsonl")) enc := json.NewEncoder(f) for _, name := range sortedKeys(tests.Pass) { msg := compact(tests.Pass[name]) var v root.Root if err := json.Unmarshal(msg, &v); err != nil { fmt.Fprintf(os.Stderr, "pass.%s: unexpected error with %s: %v\n", name, msg, err) failed = true } try(enc.Encode(&v)) } for _, name := range sortedKeys(tests.Fail.CUE) { msg := compact(tests.Fail.CUE[name]) var v root.Root if err := json.Unmarshal(tests.Fail.CUE[name], &v); err != nil { fmt.Fprintf(os.Stderr, "fail.cue.%s: unexpected error with %s: %v\n", name, msg, err) failed = true } } for _, name := range sortedKeys(tests.Fail.Both) { msg := compact(tests.Fail.Both[name]) var v root.Root if err := json.Unmarshal(msg, &v); err == nil { fmt.Fprintf(os.Stderr, "fail.both.%s: expected error with %s\n", name, msg) failed = true } } try(f.Close()) if failed { os.Exit(1) } } // TODO: maps.Keys func sortedKeys(m map[string]json.RawMessage) []string { var keys []string for k := range m { keys = append(keys, k) } slices.Sort(keys) return keys } func compact(msg json.RawMessage) []byte { var buf bytes.Buffer try(json.Compact(&buf, []byte(msg))) return buf.Bytes() } func try(err error) { if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func try1[T any](t T, err error) T { if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } return t } -- rootval/root.cue -- package rootval import "foo.test/bar/root" root.#root -- root/root.cue -- package root // This type is always overriden via @go() attributes, and it is hidden, // so it should never be generated. _#overridenNeverGenerate: string #emptyStruct: {} #root: { // TODO: keep the embedding on the Go side to avoid repeating types #embeddedStruct types?: #types fields?: { regular: int required?: int // Optional types are represented as *T in Go if they are structs. optional?: int optionalNullable?: [...int] optionalStruct?: #emptyStruct optionalStructAttrType?: #emptyStruct @go(,type=EmptyStruct) regularStruct: field?: int useRegular?: regular useRegularStruct?: regularStruct } // Hidden fields are not generated. _hiddenNeverGenerate: int attrName?: int @go(AttrChangedName) attrNameNested?: int @go(AttrChangedNameNested) attrType?: _#overridenNeverGenerate @go(,type=go/constant.Kind) // For compatibility with `cue get go`, an unnamed second value is also a type. attrTypeCompat?: _#overridenNeverGenerate @go(,go/token.Token) attrTypeNested?: {one?: two?: three?: int} @go(,type=map[any]any) attrIgnoreNeverGenerate?: int @go(-) // doc is a great field. // // It deserves multiple paragraphs of documentation // as there is a lot to write about it. doc?: int inlineDoc?: int // this is an inline comment innerDoc?: { // This is documentation inside a struct, but not attached to any of its fields. innerDocField?: int } #innerStruct: innerStructField?: int useInnerStruct?: #innerStruct _#hiddenInnerStruct: innerStructField?: int useHiddenInnerStruct?: _#hiddenInnerStruct deeplyNested?: one?: two?: three?: int useHiddenStruct?: _#hiddenStruct // Hidden definitions are only generated if referenced; this one is not. _#unusedHiddenInnerStruct: neverGenerate?: int // Nested definitions are still exported via the CUE package, // but it's not clear whether we should generate them as Go types. // They might be template parameters, for example. // For now we don't generate them. #unusedInnerStruct: neverGenerate?: int discriminatorField?: close({one!: int}) | close({two!: int}) mustEqual1?: int mustEqual2?: mustEqual1 } // Actually, this field needed even more documentation. #root: doc?: _ // All definitions underneath here must not be exported. _#hiddenStruct: { innerField?: int #innerStruct: field?: int innerStruct?: #innerStruct } #embeddedStruct: { embedded1?: int { embedded2?: int } } // Hidden definitions are only generated if referenced; this one is not. _#unusedHiddenStruct: neverGenerate?: int #attrName: int @go(AttrChangedName) #attrNameEmbed: { @go(AttrChangedNameEmbed) field?: int } #attrType: _#overridenNeverGenerate @go(,type=go/constant.Kind) #attrTypeEmbed: { @go(,type=go/constant.Kind) // obeyed even when the type has a different kind neverGenerate?: int } #attrIgnoreNeverGenerate: int @go(-) #attrIgnoreEmbedNeverGenerate: { @go(-) neverGenerate?: int } -- root/types.cue -- package root import ( "list" "time" ) #types: { // The field names below are capitalized to avoid name clashes. Top?: _ // Do we care about bottom? Null?: null Bool?: bool Int?: int Float?: float String?: string Bytes?: bytes Number?: number Uint?: uint Int8?: int8 Rune?: rune IntList?: [...int] IntListClosed2?: [int, int] IntMap?: [string]: int Time?: time.Time Duration?: time.Duration StringOrInt?: string | int StringOrIntDefault?: string | *int NullOrStruct?: null | {foo?: int} NullOrString?: null | string NumericBounds?: >0 & <100 NonEmptyString?: string & != "" UniqueStrings?: list.UniqueItems & [... string] LinkedList?: #linkedList } #linkedList: { item?: _ next?: #linkedList } -- root/import.cue -- package root import ( "foo.test/bar/imported/multipkg:multipkg_one" "foo.test/bar/imported/multipkg:multipkg_two" "foo.test/bar/imported/subinst:imported" "foo.test/bar/imported/unused" ) #remoteStructs: { inst?: imported.#instanceStruct lowerRegular?: imported.lowerRegular UpperRegular?: imported.UpperRegular lowerDef?: imported.#lowerDef UpperDef?: imported.#UpperDef multiOne?: multipkg_one.#One multiTwo?: multipkg_two.#Two } _unusedImport: unused.#UnusedNeverGenerate -- root/cue_types_gen.go.want -- // Code generated by "cue exp gengotypes"; DO NOT EDIT. package root import ( "foo.test/bar/imported/multipkg" "foo.test/bar/imported/subinst" "go/constant" "go/token" "time" ) type RemoteStructs struct { Inst *imported.InstanceStruct `json:"inst,omitempty"` LowerRegular int64 `json:"lowerRegular,omitempty"` UpperRegular int64 `json:"UpperRegular,omitempty"` LowerDef imported.LowerDef `json:"lowerDef,omitempty"` UpperDef imported.UpperDef `json:"UpperDef,omitempty"` MultiOne multipkg_one.One `json:"multiOne,omitempty"` MultiTwo multipkg_two.Two `json:"multiTwo,omitempty"` } type Types struct { Top any/* CUE top */ `json:"Top,omitempty"` Null *struct{}/* CUE null */ `json:"Null,omitempty"` Bool bool `json:"Bool,omitempty"` Int int64 `json:"Int,omitempty"` Float float64 `json:"Float,omitempty"` String string `json:"String,omitempty"` Bytes []byte `json:"Bytes,omitempty"` Number any/* CUE number; int64 or float64 */ `json:"Number,omitempty"` Uint int64 `json:"Uint,omitempty"` Int8 int64 `json:"Int8,omitempty"` Rune int64 `json:"Rune,omitempty"` IntList []int64 `json:"IntList,omitempty"` IntListClosed2 []any/* CUE closed list */ `json:"IntListClosed2,omitempty"` IntMap map[string]int64 `json:"IntMap,omitempty"` Time time.Time `json:"Time,omitempty"` Duration string/* CUE time.Duration */ `json:"Duration,omitempty"` StringOrInt any/* CUE disjunction: (int|string) */ `json:"StringOrInt,omitempty"` StringOrIntDefault any/* CUE disjunction: (int|string) */ `json:"StringOrIntDefault,omitempty"` NullOrStruct any/* CUE disjunction: (null|struct) */ `json:"NullOrStruct,omitempty"` NullOrString any/* CUE disjunction: (null|string) */ `json:"NullOrString,omitempty"` NumericBounds any/* CUE number; int64 or float64 */ `json:"NumericBounds,omitempty"` NonEmptyString string `json:"NonEmptyString,omitempty"` UniqueStrings []string `json:"UniqueStrings,omitempty"` LinkedList *LinkedList `json:"LinkedList,omitempty"` } type LinkedList struct { Item any/* CUE top */ `json:"item,omitempty"` Next *LinkedList `json:"next,omitempty"` } type EmptyStruct struct { } type Root struct { Embedded1 int64 `json:"embedded1,omitempty"` Embedded2 int64 `json:"embedded2,omitempty"` Types *Types `json:"types,omitempty"` Fields *struct { Regular int64 `json:"regular"` Required int64 `json:"required,omitempty"` // Optional types are represented as *T in Go if they are structs. Optional int64 `json:"optional,omitempty"` OptionalNullable []int64 `json:"optionalNullable,omitempty"` OptionalStruct *EmptyStruct `json:"optionalStruct,omitempty"` OptionalStructAttrType EmptyStruct `json:"optionalStructAttrType,omitempty"` RegularStruct struct { Field int64 `json:"field,omitempty"` } `json:"regularStruct"` UseRegular int64 `json:"useRegular,omitempty"` UseRegularStruct *struct { Field int64 `json:"field,omitempty"` } `json:"useRegularStruct,omitempty"` } `json:"fields,omitempty"` AttrChangedName int64 `json:"attrName,omitempty"` AttrChangedNameNested int64 `json:"attrNameNested,omitempty"` AttrType constant.Kind `json:"attrType,omitempty"` // For compatibility with `cue get go`, an unnamed second value is also a type. AttrTypeCompat token.Token `json:"attrTypeCompat,omitempty"` AttrTypeNested map[any]any `json:"attrTypeNested,omitempty"` // doc is a great field. // // It deserves multiple paragraphs of documentation // as there is a lot to write about it. // // Actually, this field needed even more documentation. Doc int64 `json:"doc,omitempty"` InlineDoc int64 `json:"inlineDoc,omitempty"` InnerDoc *struct { InnerDocField int64 `json:"innerDocField,omitempty"` } `json:"innerDoc,omitempty"` UseInnerStruct *Root_innerStruct `json:"useInnerStruct,omitempty"` UseHiddenInnerStruct *root_hiddenInnerStruct `json:"useHiddenInnerStruct,omitempty"` DeeplyNested *struct { One *struct { Two *struct { Three int64 `json:"three,omitempty"` } `json:"two,omitempty"` } `json:"one,omitempty"` } `json:"deeplyNested,omitempty"` UseHiddenStruct *hiddenStruct `json:"useHiddenStruct,omitempty"` DiscriminatorField map[string]any `json:"discriminatorField,omitempty"` MustEqual1 int64 `json:"mustEqual1,omitempty"` MustEqual2 any/* TODO: IncompleteKind: _|_ */ `json:"mustEqual2,omitempty"` } type EmbeddedStruct struct { Embedded1 int64 `json:"embedded1,omitempty"` Embedded2 int64 `json:"embedded2,omitempty"` } type AttrChangedName int64 type AttrType constant.Kind type Root_innerStruct struct { InnerStructField int64 `json:"innerStructField,omitempty"` } type root_hiddenInnerStruct struct { InnerStructField int64 `json:"innerStructField,omitempty"` } // All definitions underneath here must not be exported. type hiddenStruct struct { InnerField int64 `json:"innerField,omitempty"` InnerStruct *hiddenStruct_innerStruct `json:"innerStruct,omitempty"` } type hiddenStruct_innerStruct struct { Field int64 `json:"field,omitempty"` } -- imported/imported.cue -- package imported import "foo.test/bar/imported/indirect" // These should be ignored as they are not exported definitions. regularNeverGenerate: string _hiddenNeverGenerate: string #instanceStruct: { instanceField: int indirectField: indirect.#Indirect } -- imported/subinst/imported.cue -- package imported #instanceStruct: _ lowerRegular: int UpperRegular: int #lowerDef: int #UpperDef: int -- imported/subinst/cue_types_imported_gen.go.want -- // Code generated by "cue exp gengotypes"; DO NOT EDIT. package imported import ( "foo.test/bar/imported/indirect" ) type InstanceStruct struct { InstanceField int64 `json:"instanceField"` IndirectField indirect.Indirect `json:"indirectField"` } type LowerDef int64 type UpperDef int64 -- imported/indirect/indirect.cue -- package indirect #Indirect: int -- imported/indirect/cue_types_gen.go.want -- // Code generated by "cue exp gengotypes"; DO NOT EDIT. package indirect type Indirect int64 -- imported/unused/unused.cue -- package unused // This API and package are not used as part of the generated schemas. #UnusedNeverGenerate: int -- imported/multipkg/one.cue -- package multipkg_one @go(multipkg) #One: int -- imported/multipkg/two.cue -- package multipkg_two @go(multipkg) #Two: int -- imported/multipkg/cue_types_multipkg_one_gen.go.want -- // Code generated by "cue exp gengotypes"; DO NOT EDIT. package multipkg type One int64 -- imported/multipkg/cue_types_multipkg_two_gen.go.want -- // Code generated by "cue exp gengotypes"; DO NOT EDIT. package multipkg type Two int64 -- bad_syntax/invalid.cue -- package bad_syntax // This CUE package is not referenced nor used anywhere, so it should not be loaded. { bad syntax cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/experiment_unknown.txtar000066400000000000000000000001711474664451600267210ustar00rootroot00000000000000env CUE_EXPERIMENT=xxx ! exec cue eval something cmp stderr errout -- errout -- cannot parse CUE_EXPERIMENT: unknown xxx cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export.txtar000066400000000000000000000004701474664451600243050ustar00rootroot00000000000000exec cue export ./hello cmp stdout expect-stdout -- expect-stdout -- { "$type": "demo", "message": "Hello World!" } -- hello/data.cue -- package hello #who: "World" -- hello/hello.cue -- package hello $type: "demo" message: "Hello \(#who)!" // who declared in data.cue -- hello/cue.mod/module.cue -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_cue.txtar000066400000000000000000000020161474664451600251370ustar00rootroot00000000000000# Verify that -p works when exporting as CUE. # Case 1: only non-CUE inputs exec cue export --out cue -p blah x.json y.json cmp stdout stdout.golden # Case 2: CUE input which does not declare a package (with JSON) exec cue export --out cue -p blah nopkg.cue x.json y.json cmp stdout stdout.golden # Case 3: CUE input which does declare same package (with JSON) exec cue export --out cue -p blah pkg.cue x.json y.json cmp stdout stdout.golden # Case 4: CUE input with mis-matched package (with JSON) # # TODO: in the future we could allow "repackaging" via --force which would # cause this export to succeed with the package clause 'blah' in the result. ! exec cue export --out cue -p blah diffpkg.cue x.json y.json cmp stderr stderr.golden -- x.json -- { "x": 5 } -- y.json -- { "y": 4 } -- nopkg.cue -- x: 5 y: 4 -- pkg.cue -- package blah x: 5 y: 4 -- diffpkg.cue -- package other x: 5 y: 4 -- stdout.golden -- package blah x: 5 y: 4 -- stderr.golden -- "package" flag clashes with existing package name (blah vs other) cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_defaulterr.txtar000066400000000000000000000011711474664451600265210ustar00rootroot00000000000000#Issue 1304 ! exec cue export --out json x.cue cmp stdout expect_stdout_json cmp stderr expect_stderr_json ! exec cue export --out cue x.cue cmp stdout expect_stdout_cue cmp stderr expect_stderr_cue ! exec cue export --out yaml x.cue cmp stdout expect_stdout_yaml cmp stderr expect_stderr_yaml -- x.cue -- toto: value: *_|_ | (*"toto" | string) -- expect_stdout_cue -- -- expect_stderr_cue -- toto.value: incomplete value "toto" | string -- expect_stdout_json -- -- expect_stderr_json -- toto.value: incomplete value "toto" | string -- expect_stdout_yaml -- -- expect_stderr_yaml -- toto.value: incomplete value "toto" | string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_err.txtar000066400000000000000000000020371474664451600251560ustar00rootroot00000000000000! exec cue eval ./exporterr --out json cmp stdout expect-stdout cmp stderr expect-stderr ! exec cue eval ./exporterr -c cmp stdout expect-stdout cmp stderr expect-stderr ! exec cue export ./exporterr cmp stdout expect-stdout cmp stderr expect-stderr ! exec cue export repeated.cue -o openapi:export.json ! stdout . cmp stderr expect-stderr-openapi ! exec cue eval repeated.cue --out openapi ! stdout . cmp stderr expect-stderr-openapi -- repeated.cue -- info: { title: "test title" } info: { title: "test title 2" } -- expect-stderr-openapi -- info.title: conflicting values "test title 2" and "test title": ./repeated.cue:2:12 ./repeated.cue:6:12 -- expect-stderr -- a.b.2.c: incomplete value int: ./exporterr/export_err.cue:3:18 out: invalid interpolation: undefined field: d: ./exporterr/export_err.cue:7:6 ./exporterr/export_err.cue:7:16 -- expect-stdout -- -- exporterr/export_err.cue -- package exporterr a: b: [0, 1, {c: int}, 3] // Issue #553 b: c: "hello" out: "d is \(b.d)" -- exporterr/cue.mod/module.cue -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_escape.txtar000066400000000000000000000010111474664451600256150ustar00rootroot00000000000000# Verify that export with and without --escape works as expected. exec cue export --out json file.cue cmp stdout stdout.golden exec cue export --out json --escape file.cue cmp stdout stdout-escape.golden -- file.cue -- package hello simple: "hello" specialJSON: #"\ ""# specialHTML: "& < >" -- stdout.golden -- { "simple": "hello", "specialJSON": "\\ \"", "specialHTML": "& < >" } -- stdout-escape.golden -- { "simple": "hello", "specialJSON": "\\ \"", "specialHTML": "\u0026 \u003c \u003e" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_expr.txtar000066400000000000000000000011741474664451600253450ustar00rootroot00000000000000cd simple exec cue export data.cue -e a+c -e d.e.f --out yaml cmp stdout expect-stdout cd .. # Issue 2542 was a regression introduced in CUE v0.6 which was resolved by evalv3. env CUE_EXPERIMENT=evalv3 cd issue2542 exec cue export -e 'obj2.name' input.cue cmp stdout stdout.golden cd .. -- simple/expect-stdout -- 4 --- jam -- simple/data.cue -- a: 1 c: 3 d: e: f: "jam" -- issue2542/input.cue -- obj: this={ (#makeName & {enable: this._enable}).out } obj: _enable: true obj2: obj #makeName: { enable: bool if enable { out: name: "enabled" } if !enable { out: name: "disabled" } } -- issue2542/stdout.golden -- "enabled" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_force.txtar000066400000000000000000000031031474664451600254570ustar00rootroot00000000000000# Verify that export with --force works # First time should simply succeed exec cue export -o test.yml file.cue cmp test.yml test.yml.golden # Second time will fail without --force ! exec cue export -o test.yml file.cue stderr 'error writing "test.yml": file already exists' # Second time with --force should succeed exec cue export --force -o test.yml file.cue cmp test.yml test.yml.golden # With or without --force, we should fail to output to a file inside a missing directory. ! exec cue export -o /definitely/does/not/exist/test.yml file.cue ! exec cue export --force -o /definitely/does/not/exist/test.yml file.cue # Two concurrent exports to the same new file without --force; # only one should succeed. We use a relatively slow bit of CUE # to make it likely that both export operations begin before either # has finished and created the resulting output file. # Since it's a coin toss which command wins the race, # we allow both to fail but expect the joint stderr to contain exactly one error. exec cue_exitzero export -o conflict.yml slow.cue & exec cue_exitzero export -o conflict.yml slow.cue & wait stderr -count=1 'error writing "conflict.yml": file already exists' exists conflict.yml # Now with --force; the two commands should always succeed. exec cue export --force -o conflict_force.yml slow.cue & exec cue export --force -o conflict_force.yml slow.cue & wait exists conflict_force.yml -- file.cue -- package hello #who: "World" message: "Hello \(#who)!" -- test.yml.golden -- message: Hello World! -- slow.cue -- package hello import "list" out: list.Repeat(["x"], 2000) cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_incomplete.txtar000066400000000000000000000013351474664451600265250ustar00rootroot00000000000000# TODO: line numbers for errors. #Issue 1153 #Issue 1152 # Default export mode ! exec cue export x.cue cmp stderr out/stderr # JSON ! exec cue export --out json x.cue cmp stderr out/stderr # Yaml ! exec cue export --out yaml x.cue cmp stderr out/stderr # CUE data ! exec cue export --out cue x.cue cmp stderr out/stderr # Concrete ! exec cue eval -c x.cue cmp stderr out/stderr # CUE exec cue eval --out cue x.cue cmp stdout expect-cue -- x.cue -- package foo #SomeBaseType: { "a" | "b" #AUTO: "z" } V1: ("x" | "y") | *"z" V2: ("x" | "y") | *#SomeBaseType.#AUTO -- expect-cue -- #SomeBaseType: { "a" #AUTO: "z" } | { "b" #AUTO: "z" } V1: "z" V2: "x" | "y" -- out/stderr -- V2: incomplete value "x" | "y" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_issue3511.txtar000066400000000000000000000010401474664451600260210ustar00rootroot00000000000000 env CUE_EXPERIMENT=evalv3=1 exec cue export cmp stdout out/stdout -- cue.mod/module.cue -- module: "module.test/foo" language: version: "v0.9.0" -- main.cue -- package p import "module.test/foo/imported@v0" items: [imported.List] -- imported/imported.cue -- package imported Namespace: "default" List: [...{namespace: Namespace}] List: [{name: "kube-api-server"}] -- out/stdout -- { "items": [ [ { "namespace": "default", "name": "kube-api-server" } ] ] } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_issue3616.txtar000066400000000000000000000024131474664451600260340ustar00rootroot00000000000000# https://cuelang.org/issue/3616 # # The old evaluator (evalv2) does not correctly handle some combination of the # scenario below, which involves "copying" values and the use of -l for a # non-CUE file. The precise reason that evalv2 does not fail as expected is not # known. But given we are close to switching to evalv3 by default, and all # efforts and fixed are geared in that direction, adding this test to lock in # the behaviour of evalv3 (and evalv2 for that matter) is deemed sufficient. # With evalv3, we get an error as expected. env CUE_EXPERIMENT=evalv3 ! exec cue export --with-context -l '_input:' -l 'filename' x.cue data.json stderr 'notAllowed: field not allowed' # But with evalv2, it's incorrectly allowed. i.e. the following cue export # command should fail (with the error message in the inverted stderr # expectation) but doesn't. env CUE_EXPERIMENT=evalv3=0 exec cue export --with-context -l '_input:' -l 'filename' x.cue data.json ! stderr 'notAllowed: field not allowed' -- x.cue -- #schema: aField!: bool _parameters & #schema _parameters: #template #template: { #in: _input for _name, _content in #in { _content.parameters } } _input: {} -- data.json -- { "parameters": { "aField": true, "notAllowed": true } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_list.txtar000066400000000000000000000014251474664451600253410ustar00rootroot00000000000000exec cue export -l "\(strings.ToLower(kind))" --list import/services.jsonl cmp stdout expect-stdout -- expect-stdout -- { "service": [ { "kind": "Service", "name": "booster" }, { "kind": "Service", "name": "supplement\nfoo", "json": "[1, 2]" } ], "deployment": [ { "kind": "Deployment", "name": "booster", "replicas": 1 } ] } -- import/services.jsonl -- { "kind": "Service", "name": "booster" } { "kind": "Deployment", "name": "booster", "replicas": 1 } { "kind": "Service", "name": "supplement\nfoo", "json": "[1, 2]" } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_required.txtar000066400000000000000000000006721474664451600262110ustar00rootroot00000000000000#Issue #2336 exec cue export x.cue cmp stdout stdout.golden #Issue #2307 ! exec cue export y.cue cmp stderr stderr.golden -- x.cue -- #Person: { name!: string age?: int } -- stdout.golden -- {} -- y.cue -- a: x!: 5 a: x?: int // do not include this position #Def: { x!: int } b: #Def -- stderr.golden -- a.x: field is required but not present: ./y.cue:1:4 b.x: field is required but not present: ./y.cue:5:2 ./y.cue:8:4 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_select.txtar000066400000000000000000000004711474664451600256450ustar00rootroot00000000000000exec cue export .:foo mod.test/bar:baz cmp stdout expect-stdout -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- foo.cue -- package foo a: 1 -- bar.cue -- package bar b: 1 -- expect-stdout -- { "a": 1 } { "c": 1 } -- cue.mod/gen/mod.test/bar/bar.cue -- package baz c:1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/export_yaml.txtar000066400000000000000000000006321474664451600253270ustar00rootroot00000000000000exec cue export --out yaml ./hello cmp stdout expect-stdout -- expect-stdout -- message: Hello World! test: {} -- hello/data.cue -- package hello _who: "World" -- hello/hello.cue -- package hello message: "Hello \(_who)!" // who declared in data.cue test: { _foo: string // technically in error, but test anyway. if *(len(_foo) > 0) | false { command: ["foo", "bar"] } } -- hello/cue.mod/module.cue -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/file_forms.txtar000066400000000000000000000007221474664451600251110ustar00rootroot00000000000000exec cue eval data: foo.cue cmp stdout expect-data-foo ! exec cue eval data: bar.cue cmp stderr expect-data-bar exec cue eval graph: bar.cue cmp stdout expect-graph-bar -- foo.cue -- a: 4 b: { c: 1 } // Duplicates are still allowed. b: { d: 2 } -- bar.cue -- a: 4 b: { c: a } -- expect-data-foo -- a: 4 b: { c: 1 d: 2 } -- expect-data-bar -- references not allowed in data mode: ./bar.cue:3:8 -- expect-graph-bar -- a: 4 b: { c: 4 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fix.txtar000066400000000000000000000013731474664451600235550ustar00rootroot00000000000000# Just like other commands, we can fix with stdin/stdout. stdin p/three.cue exec cue fix - cmp stdout p/three.cue.fixed # Make sure we fix all files in a directory, even if they're a mix of packages (or no packages). exec cue fix ./... cmp p/one.cue p/one.cue.fixed cmp p/two.cue p/two.cue.fixed cmp p/three.cue p/three.cue.fixed -- p/one.cue -- package one out: ["foo"] + ["bar"] -- p/two.cue -- package two out: 3 * ["baz"] -- p/three.cue -- out: ["a"] + ((["a"]*7) + ["gh"]) -- p/one.cue.fixed -- package one import "list" out: list.Concat([["foo"], ["bar"]]) -- p/two.cue.fixed -- package two import "list" out: list.Repeat(["baz"], 3) -- p/three.cue.fixed -- import "list" out: list.Concat([["a"], (list.Concat([(list.Repeat(["a"], 7)), ["gh"]]))]) cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt.txtar000066400000000000000000000011361474664451600235520ustar00rootroot00000000000000! exec cue fmt ./fmt cmp stderr expect-stderr # Issue 1744: if we encounter an error while formatting, # don't overwrite the input file with zero bytes. cp issue1744/invalid.cue issue1744/invalid.cue.orig ! exec cue fmt issue1744/invalid.cue cmp stderr issue1744/stderr-golden cmp issue1744/invalid.cue issue1744/invalid.cue.orig -- expect-stderr -- expected 'STRING', found '.': ./fmt/error.cue:1:9 -- fmt/error.cue -- import a.b "foo" a: 2 bb: 3 -- fmt/cue.mod/module.cue -- -- issue1744/invalid.cue -- ~ -- issue1744/stderr-golden -- illegal character U+007E '~': ./issue1744/invalid.cue:1:1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_check.txtar000066400000000000000000000031651474664451600247130ustar00rootroot00000000000000cd standalone # succeeds with no output when file is formatted exec cue fmt --check formatted.cue ! stdout . stdin formatted.cue exec cue fmt --check - ! stdout . # fails and displays non formatted files ! exec cue fmt --check not_formatted.cue another/not_formatted.cue cmpenv stdout expected-output # files are not modified with --check # running twice returns the same file list ! exec cue fmt --check not_formatted.cue another/not_formatted.cue cmpenv stdout expected-output # stdin fails with indicative output stdin not_formatted.cue ! exec cue fmt --check - cmp stdout stdin-expected-output # fails with indicative output when both stdin and files provided stdin not_formatted.cue ! exec cue fmt --check - another/not_formatted.cue cmpenv stdout stdin-mixed-expected-output cd ../module # files are printed relative to CWD ! exec cue fmt --check ./... cmpenv stdout stdout.golden cd example ! exec cue fmt --check ./... cmp stdout stdout.golden -- standalone/formatted.cue -- foo: "bar" -- standalone/not_formatted.cue -- foo: "bar" -- standalone/another/not_formatted.cue -- bar: "baz" x: 1 -- standalone/expected-output -- not_formatted.cue another${/}not_formatted.cue -- standalone/stdin-expected-output -- - -- standalone/stdin-mixed-expected-output -- - another${/}not_formatted.cue -- module/cue.mod/module.cue -- module: "example.com" language: version: "v0.9.0" -- module/not_formatted.cue -- package module foo: "bar" -- module/stdout.golden -- not_formatted.cue example${/}not_formatted.cue -- module/example/not_formatted.cue -- package module foo: "bar" -- module/example/stdout.golden -- not_formatted.cue cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_diff.txtar000066400000000000000000000016121474664451600245410ustar00rootroot00000000000000# no output when file is formatted exec cue fmt --diff formatted.cue ! stdout . exec cue fmt -d formatted.cue ! stdout . # displays diff when file is not formatted exec cue fmt --diff not-formatted.cue cmp stdout not-formatted-diff.golden exec cue fmt -d not-formatted.cue cmp stdout not-formatted-diff.golden # exits with error when --check is set ! exec cue fmt --check --diff not-formatted.cue cmp stdout not-formatted-diff.golden # displays diff when file is stdin (-) stdin not-formatted.cue exec cue fmt --diff - cmp stdout not-formatted-stdin.golden -- formatted.cue -- foo: "bar" -- not-formatted.cue -- foo: "bar" -- not-formatted-diff.golden -- diff not-formatted.cue.orig not-formatted.cue --- not-formatted.cue.orig +++ not-formatted.cue @@ -1,1 +1,1 @@ -foo: "bar" +foo: "bar" -- not-formatted-stdin.golden -- diff -.orig - --- -.orig +++ - @@ -1,1 +1,1 @@ -foo: "bar" +foo: "bar" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_err.txtar000066400000000000000000000021501474664451600244170ustar00rootroot00000000000000# Fail when import path provided as argument is invalid. ! exec cue fmt ./non-existing-file cmp stderr non-existing-file.golden # Ignore certain package loading errors in cue fmt. cd issue644 exec cue fmt x.cue exec cue fmt ./... cmp x.cue out/x_cue cd .. cd issue728 exec cue fmt x.cue exec cue fmt ./... cmp x.cue out/x_cue cd .. cd issue1938 exec cue fmt x.cue y.cue cmp x.cue out/x_cue cmp y.cue out/y_cue cd .. -- non-existing-file.golden -- cannot find package "./non-existing-file" -- cue.mod/module.cue -- module: "mod.test/x" language: version: "v0.9.0" -- emptypkg/.empty -- -- issue644/x.cue -- package x import "mod.test/x/nosuchpkg" x: 5 y: unresolved -- issue644/out/x_cue -- package x import "mod.test/x/nosuchpkg" x: 5 y: unresolved -- issue728/x.cue -- package x import "mod.test/x/emptypkg" x: 5 -- issue728/out/x_cue -- package x import "mod.test/x/emptypkg" x: 5 -- issue1938/x.cue -- package x import "mod.test/x/nosuchpkg" x: 5 -- issue1938/out/x_cue -- package x import "mod.test/x/nosuchpkg" x: 5 -- issue1938/y.cue -- package y y: 6 -- issue1938/out/y_cue -- package y y: 6 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_files.txtar000066400000000000000000000054101474664451600247330ustar00rootroot00000000000000# succeeds when all files are well formatted exec cue fmt --files --check standalone/a/ # prints files that are not well formatted, recursively ! exec cue fmt --files --check standalone/b cmpenv stdout standalone/b/stdout-golden # regular files can be passed as an argument with or without files ! exec cue fmt --files --check standalone/b/c/not-formatted.cue standalone/b/not-formatted.cue cmpenv stdout standalone/b/stdout-golden # file can be passed via stdin stdin standalone/stdin/not-formatted.cue ! exec cue fmt --files --check - cmpenv stdout standalone/stdin/stdout-check-golden stdin standalone/stdin/not-formatted.cue exec cue fmt --files - cmpenv stdout standalone/stdin/stdout-golden # current directory is used when no args provided cd noargs ! exec cue fmt --files --check cmpenv stdout stdout-golden cd .. # directories beginning with _ or . are ignored exec cue fmt --files --check standalone/hidden/ # directories beginning with _ or . are processed when passed explicitly ! exec cue fmt --files --check standalone/hidden/_temp/ standalone/hidden/.temp/ cmpenv stdout standalone/hidden/stdin-golden # files under cue.mod are ignored exec cue fmt --files --check mod ! stdout . # files under cue.mod are processed when passed explicitly ! exec cue fmt --files --check mod/cue.mod/ cmpenv stdout mod/stdout-golden # exit early if user attempts to use ... patterns ! exec cue fmt --files --check standalone/a/... stderr 'cannot use "..." in --files mode' ! stdout . ! exec cue fmt --files --check h... stderr 'cannot use "..." in --files mode' ! stdout . -- standalone/a/formatted.cue -- foo: "bar" -- standalone/b/not-formatted.cue -- x: 1 -- standalone/b/c/not-formatted.cue -- foo: "bar" -- standalone/hidden/_temp/not-formatted.cue -- foo: "bar" -- standalone/hidden/.temp/not-formatted.cue -- foo: "bar" -- standalone/hidden/stdin-golden -- standalone${/}hidden${/}_temp${/}not-formatted.cue standalone${/}hidden${/}.temp${/}not-formatted.cue -- standalone/b/stdout-golden -- standalone${/}b${/}c${/}not-formatted.cue standalone${/}b${/}not-formatted.cue -- standalone/stdin/not-formatted.cue -- foo: "bar" -- standalone/stdin/stdout-golden -- foo: "bar" -- standalone/stdin/stdout-check-golden -- - -- mod/cue.mod/gen/not-formatted.cue -- foo: "bar" -- mod/cue.mod/usr/not-formatted.cue -- foo: "bar" -- mod/cue.mod/pkg/not-formatted.cue -- foo: "bar" -- mod/cue.mod/module.cue -- module: "example.com" language: { version: "v0.9.3" } -- mod/stdout-golden -- mod${/}cue.mod${/}gen${/}not-formatted.cue mod${/}cue.mod${/}module.cue mod${/}cue.mod${/}pkg${/}not-formatted.cue mod${/}cue.mod${/}usr${/}not-formatted.cue -- noargs/file.cue -- foo: "bar" -- noargs/dir/another-file.cue -- foo: "bar" -- noargs/stdout-golden -- dir${/}another-file.cue file.cuecue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_filetypes.txtar000066400000000000000000000026151474664451600256410ustar00rootroot00000000000000# Verify how fmt behaves with different encodings. exec cue fmt --diff input.cue cmp stdout input.cue.diff # Unknown file extensions fail on their own ! exec cue fmt --diff input.cue-unknown stderr 'unknown file extension' # Unknown file extensions work if we specify them as CUE. cp input.cue input.cue-unknown exec cue fmt --diff cue: input.cue-unknown cmp stdout input.cue-unknown.diff # TODO(mvdan): we should probably fail rather than doing nothing. exec cue fmt --diff input.json ! stdout . ! stderr . # JSON is valid CUE syntax, so it can be formatted as CUE, if one wants to. exec cue fmt --diff cue: input.json cmp stdout input.json.diff # TODO(mvdan): we should probably fail rather than doing nothing. exec cue fmt --diff input.yaml ! stdout . ! stderr . # YAML in this case is not valid CUE. ! exec cue fmt --diff cue: input.yaml stderr 'in struct literal' -- input.cue -- foo: "bar" -- input.cue.diff -- diff input.cue.orig input.cue --- input.cue.orig +++ input.cue @@ -1,1 +1,1 @@ -foo: "bar" +foo: "bar" -- input.cue-unknown.diff -- diff input.cue-unknown.orig input.cue-unknown --- input.cue-unknown.orig +++ input.cue-unknown @@ -1,1 +1,1 @@ -foo: "bar" +foo: "bar" -- input.json -- {"foo": "bar"} -- input.json.diff -- diff input.json.orig input.json --- input.json.orig +++ input.json @@ -1,1 +1,1 @@ -{"foo": "bar"} +{"foo": "bar"} -- input.yaml -- foo: - unquoted bar cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_import_no_module.txtar000066400000000000000000000005051474664451600272040ustar00rootroot00000000000000# This tests that when there's an import and no current module, # fmt will still work with both stdin and files. stdin a/x.cue exec cue fmt - cmp stdout a.cue-want exec cue fmt a/x.cue cmp a/x.cue a.cue-want -- a/x.cue -- package x import "mod.com/p" x: p.p -- a.cue-want -- package x import "mod.com/p" x: p.p cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_issue1553.txtar000066400000000000000000000001411474664451600252730ustar00rootroot00000000000000exec cue fmt x.cue cp x.cue x1.cue exec cue fmt x.cue cmp x.cue x1.cue -- x.cue -- [ {} // ] cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_issue1791.txtar000066400000000000000000000007401474664451600253040ustar00rootroot00000000000000# Note that the permission errors below cover unix and windows. # We can't read nor write. chmod 000 in.cue ! exec cue fmt in.cue stderr 'permission denied|Access is denied' # We can read, but not write. We used to ignore some open/write errors. chmod 444 in.cue ! exec cue fmt in.cue stderr 'permission denied|Access is denied' # We can read and write. chmod 666 in.cue exec cue fmt in.cue cmp in.cue in.cue.golden -- in.cue -- foo: "bar" -- in.cue.golden -- foo: "bar" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_issue3329.txtar000066400000000000000000000006641474664451600253100ustar00rootroot00000000000000# Issue 3329: this failed with a "no dependency found" error. exec cue fmt ./... cmp bar/bar.cue bar.cue.golden cmp bar/nonpkg.cue nonpkg.cue.golden -- bar.cue.golden -- package bar x: true -- nonpkg.cue.golden -- import "cue.example/foo/bar" bar -- cue.mod/module.cue -- module: "cue.example/foo" language: { version: "v0.9.0" } -- bar/bar.cue -- package bar x: true -- bar/nonpkg.cue -- import "cue.example/foo/bar" bar cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_multi.txtar000066400000000000000000000012451474664451600247650ustar00rootroot00000000000000! exec cue fmt --check . cmp stdout stdout.golden ! exec cue fmt --check x.cue star.cue y.cue yb.cue cmp stdout stdout.golden -- stdout.golden -- star.cue x.cue y.cue yb.cue -- x.cue -- // header package x // file comment a: 1 bb: 2 -- star.cue -- package _ a: 1 bb: 2 -- y.cue -- package y // a comment a: 1 bb: 2 @test(foo) -- yb.cue -- // only for prod @if(prod) package y a: 1 @test(foo) bb: 2 -- out/x.cue -- // header package x // file comment a: 1 bb: 2 -- out/star-cue -- package _ a: 1 bb: 2 -- out/y-cue -- package y // a comment a: 1 bb: 2 @test(foo) -- out/yb-cue -- // only for prod @if(prod) package y a: 1 @test(foo) bb: 2 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_parent.txtar000066400000000000000000000016531474664451600251270ustar00rootroot00000000000000# Verify that cue fmt does not format files in ancestor # directories that are part of a cue instance. ! exec cue fmt --check a/b/c/p_c.cue cmpenv stdout single-file.golden ! exec cue fmt --check a/b/c/p_c.cue a/p_a.cue cmpenv stdout multi-file.golden ! exec cue fmt --check ./a/... cmpenv stdout all-under-a.golden ! exec cue fmt --check ./a/b/c/p_c.cue ./x/p_x.cue cmpenv stdout multiple-instances.golden -- single-file.golden -- a${/}b${/}c${/}p_c.cue -- multi-file.golden -- a${/}p_a.cue a${/}b${/}c${/}p_c.cue -- all-under-a.golden -- a${/}p_a.cue a${/}b${/}p_b.cue a${/}b${/}c${/}p_c.cue -- multiple-instances.golden -- x${/}p_x.cue a${/}b${/}c${/}p_c.cue -- cue.mod/module.cue -- module: "mod.example" language: { version: "v0.9.0-alpha.1" } -- p_root.cue -- package p x: 5 -- a/p_a.cue -- package p x: 5 -- a/b/p_b.cue -- package p x: 5 -- a/b/c/p_c.cue -- package p x: 5 -- x/p_x.cue -- package p x: 5 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_simplify.txtar000066400000000000000000000004471474664451600254720ustar00rootroot00000000000000# simplify works in package mode exec cue fmt --simplify ./pkg/... cmp pkg/file.cue file.golden # simplify works in --files mode exec cue fmt --simplify --files ./files/ cmp files/file.cue file.golden -- files/file.cue -- "quoted": b -- pkg/file.cue -- "quoted": b -- file.golden -- quoted: b cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_stdin.txtar000066400000000000000000000011201474664451600247440ustar00rootroot00000000000000# Verify that `cue fmt -` always writes valid CUE provided # in stdin to stdout, even if it is well formatted. stdin not-formatted exec cue fmt - cmp stdout formatted stdin formatted exec cue fmt - cmp stdout formatted # Verify that `cue fmt -` does not write invalid CUE to stdout. stdin syntax-error ! exec cue fmt - ! stdout . cmp stderr syntax-error.stderr-golden -- syntax-error -- a: { -- syntax-error.stderr-golden -- expected '}', found 'EOF': -:1:6 -- not-formatted -- foo : 2 a: {b: 3} // a comment -- formatted -- foo: 2 a: {b: 3} // a comment -- fmt/cue.mod/module.cue -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/fmt_unchanged.txtar000066400000000000000000000003451474664451600255670ustar00rootroot00000000000000# Verify that cue fmt does not write to files # if they are already well formatted mod-time formatted.cue cp stdout mod-time.txt exec cue fmt formatted.cue mod-time formatted.cue cmp stdout mod-time.txt -- formatted.cue -- a: 1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_anon.txtar000066400000000000000000000010541474664451600252420ustar00rootroot00000000000000# Issue #1183 # Run get go exec cue get go --local . cmp a_go_gen.cue a_go_gen.cue.golden -- a.go -- package a type C int // define some typed constants const ( A C = iota b _ c ) // define some untyped constants const ( D = iota e _ f ) -- go.mod -- module mod.test/a go 1.16 -- a_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/a package a #C: int // #enumC #enumC: #A | _#b | _#c #values_C: { A: #A b: _#b c: _#c } #A: #C & 0 _#b: #C & 1 _#c: #C & 3 #D: 0 _#e: 1 _#f: 3 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_bad_embed.txtar000066400000000000000000000011251474664451600261700ustar00rootroot00000000000000# Test that we get a sensible error message when there is a type # checking error in the package that is being 'cue get go'-ed. [golang.org/issue/44287] skip exec cue get go --local exec ls cmp cue.mod/gen/mod.test/blah/blah_go_gen.cue blah.cue.golden -- go.mod -- module mod.test/blah go 1.14 -- go.mod.golden -- module mod.test/blah go 1.14 -- blah.go -- package main import _ "embed" // go:embed blah.txt var blah string type T struct { Age int } -- blah.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/blah package main #T: Age: int cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_exclude.txtar000066400000000000000000000005531474664451600257430ustar00rootroot00000000000000exec cue get go --local --exclude '^X' cmp blah_go_gen.cue blah.cue.golden -- go.mod -- module mod.test/blah go 1.18 -- blah.go -- package main type X1 string type Y1 string const X2 = 3 const Y2 = 4 -- blah.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/blah --exclude=^X package main #Y1: string #Y2: 4 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_json_compat.txtar000066400000000000000000000035041474664451600266250ustar00rootroot00000000000000# Check that the CUE generated by 'cue get go' is actually compatible # with encoding and decoding values via Go's encoding/json package. exec cue get go --local ./decls cmp decls/p_go_gen.cue decls/p_go_gen.cue.golden # Marshal via Go's encoding/json and validate with the generated CUE schema. exec go run ./marshal cp stdout go_marshal.json cmp go_marshal.json go_marshal.json.golden exec cue vet go_marshal.json schema.cue # Export from CUE and Unmarshal via Go's encoding/json. exec cue export ./decls cmp stdout cue_export.json.golden stdin stdout exec go run ./unmarshal -- schema.cue -- package schema import "mod.test/decls" decls.#Root -- go.mod -- module mod.test go 1.21 -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- decls/export.cue -- package decls #Root & { Duration: #ValueSecond } -- go_marshal.json.golden -- {"Duration":3000000000} -- cue_export.json.golden -- { "Duration": 3000000000 } -- decls/p.go -- package decls import "time" type Root struct { Duration time.Duration } const ValueSecond = 3 * time.Second -- decls/p_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/decls package decls #Root: { Duration: int @go(,time.Duration) } #ValueSecond: int & 3000000000 -- marshal/main.go -- package main import ( "encoding/json" "fmt" "log" "mod.test/decls" ) func main() { r := decls.Root{Duration: decls.ValueSecond} data, err := json.Marshal(r) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", data) } -- unmarshal/main.go -- package main import ( "encoding/json" "io" "os" "fmt" "log" "mod.test/decls" ) func main() { data, err := io.ReadAll(os.Stdin) if err != nil { log.Fatal(err) } var r decls.Root if err := json.Unmarshal(data, &r); err != nil { log.Fatal(err) } fmt.Printf("%s\n", data) } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_local.txtar000066400000000000000000000014131474664451600254000ustar00rootroot00000000000000# Test that a basic get go works using --local # All the things exec cue get go --local cmp blah_go_gen.cue all.cue.golden # Verify dependencies did not change cmp go.mod go.mod.golden # Use an alternative package name exec cue get go --local -p other cmp blah_go_gen.cue other.cue.golden # Verify dependencies did not change cmp go.mod go.mod.golden -- go.mod -- module mod.test/blah go 1.14 -- go.mod.golden -- module mod.test/blah go 1.14 -- blah.go -- package main type T struct { Age int } -- all.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/blah package main #T: Age: int -- other.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/blah package other #T: Age: int cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_non_local.txtar000066400000000000000000000047311474664451600262600ustar00rootroot00000000000000# Test that cue get go works when used without the --local flag # cue get go currently appears to act like a wrapper around go get. # But this is going to change: "cue get go" will be renamed "cue import go". # When that change happens, cue import go will assume that all # required dependencies are present, and fail otherwise. go get externalmod.test/mixfiles@v1.0.0 go mod tidy # cue get go exec cue get go externalmod.test/mixfiles cmp cue.mod/gen/externalmod.test/mixfiles/code_one_go_gen.cue cue.mod/gen/externalmod.test/mixfiles/code_one_go_gen.cue.golden cmp cue.mod/gen/externalmod.test/mixfiles/code_two_go_gen.cue cue.mod/gen/externalmod.test/mixfiles/code_two_go_gen.cue.golden cmp cue.mod/gen/externalmod.test/mixfiles/config_one_gen.cue cue.mod/gen/externalmod.test/mixfiles/config_one_gen.cue.golden cmp cue.mod/gen/externalmod.test/mixfiles/config_two_gen.cue cue.mod/gen/externalmod.test/mixfiles/config_two_gen.cue.golden # Verify dependencies are as expected cmp go.mod go.mod.golden # Verify that all transitive dependencies are generated properly as well. # If any are missing, the evaluation would fail to load them. go get externalmod.test/imports/root@v1.0.0 exec cue get go externalmod.test/imports/root exec cue vet -c uses_imports_root.cue -- cue.mod/module.cue -- module: "mod.test/local" language: version: "v0.9.0" -- uses_imports_root.cue -- package p import "externalmod.test/imports/root" root.#Type & { Sub1: Sub2: Leaf: 1 } -- go.mod -- module mod.test/local go 1.14 -- go.mod.golden -- module mod.test/local go 1.14 require externalmod.test/mixfiles v1.0.0 -- cuedeps.go -- // +build cuedeps package cuedeps import ( _ "externalmod.test/mixfiles" ) -- cue.mod/gen/externalmod.test/mixfiles/code_one_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go externalmod.test/mixfiles package mixfiles #NameOne: "Orange" -- cue.mod/gen/externalmod.test/mixfiles/code_two_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go externalmod.test/mixfiles package mixfiles #NameTwo: "Apple" -- cue.mod/gen/externalmod.test/mixfiles/config_one_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go externalmod.test/mixfiles package mixfiles Type: "Fruit" -- cue.mod/gen/externalmod.test/mixfiles/config_two_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go externalmod.test/mixfiles package mixfiles Type: string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_type_alias.txtar000066400000000000000000000006521474664451600264440ustar00rootroot00000000000000# Issue 1607 exec cue get go --local ./x cmp x/x_go_gen.cue x_go_gen.cue.golden -- go.mod -- module mod.test go 1.21 -- x/x.go -- package x import "mod.test/y" type X = y.Y -- y/y.go -- package y import "mod.test/z" type Y = z.Z -- z/z.go -- package z type Z int -- x_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/x package x import "mod.test/z" #X: z.#Z cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_type_errors.txtar000066400000000000000000000010651474664451600266660ustar00rootroot00000000000000# Test that we get expected results in the presence of type # check errors. In this mode, cue get go proceeds on a best-efforts # basis. exec cue get go --local cmp blah_go_gen.cue blah.cue.golden -- go.mod -- module mod.test/blah go 1.14 -- go.mod.golden -- module mod.test/blah go 1.14 -- blah.go -- package main import _ "embed" // go:embed blah.txt var blah string // Syntax error type S type T struct { Age int } -- blah.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/blah package main #T: Age: int cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_types.txtar000066400000000000000000000277171474664451600254710ustar00rootroot00000000000000# Test that a get go works for various "interesting" types, # including those special cases that result in _ and string # that are specifically mentioned in help get go. # # This test does not exercise with/without --local. Instead # that is left for other tests, so that this test can focus # on the various rules of get go. # Ensure we are ready for GODEBUG=gotypesalias=1 being the default # once we bump go.mod to go 1.23, or for any downstreams which # enable the GODEBUG flag themselves. env GODEBUG=gotypesalias=1 # cue get go exec cue get go --local ./... cmp ./pkg3/pkg3_go_gen.cue ./pkg3/pkg3_go_gen.cue.golden cmp ./pkg1/file1_go_gen.cue ./pkg1/file1_go_gen.cue.golden cmp ./pkg1/alias_go_gen.cue ./pkg1/alias_go_gen.cue.golden cmp ./pkg2/pkg2_go_gen.cue ./pkg2/pkg2_go_gen.cue.golden cmp ./pkg4/pkg4_go_gen.cue ./pkg4/pkg4_go_gen.cue.golden cmp ./pkg_generics/pkg_generics_go_gen.cue ./pkg_generics/pkg_generics_go_gen.cue.golden # Verify dependencies did not change cmp go.mod go.mod.golden -- go.mod -- module mod.test go 1.21 -- go.mod.golden -- module mod.test go 1.21 -- cue.mod/module.cue -- module: "mod.test" -- pkg1/alias.go -- package pkg1 import p3 "mod.test/pkg3" type MyBarzer = p3.Barzer -- pkg1/file1.go -- /* block comment */ package pkg1 import ( "encoding" "encoding/json" "time" "unsafe" p2 "mod.test/pkg2" ) // Foozer foozes a jaman. type Foozer struct { Int int String string Inline `json:",inline"` NoInline CustomJSON CustomJSON CustomYAML *CustomYAML AnyJSON json.Marshaler AnyText encoding.TextMarshaler Bar int `json:"bar,omitempty" cue:">10"` exclude int Ptr uintptr UnsafePointer unsafe.Pointer Complex64 complex64 Complex128 complex128 Byte byte // Time is mapped to CUE's internal type. Time time.Time Barzer p2.Barzer Alias1 *MyBarzer EmbedAliasInline struct{ MyBarzer `json:",inline"` } SliceAlias []MyBarzer // Note: Go encodings of protobuf tags are lossy. So this is a best-effort // thing. Map map[string]*CustomJSON `protobuf:"bytes,1,name=intf" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Slice1 []int Slice2 []interface{} Slice3 *[]json.Unmarshaler Array1 [5]int Array2 [5]interface{} Array3 *[5]json.Marshaler Array4 [5]byte Intf Interface `protobuf:"varint,2,name=intf"` Intf2 interface{} Intf3 struct{ Interface } Intf4 interface{ Foo() } // Even though this struct as a type implements MarshalJSON, it is known // that it is really only implemented by the embedded field. Embed struct{ CustomJSON } Unsupported map[int]string OptionalOmitEmptyJSON string `json:"optionalOmitEmptyJSON,omitempty"` OptionalOmitEmptyYAML string `yaml:"optionalOmitEmptyYAML,omitempty"` // +optional OptionalComment string `json:"optionalComment"` //+optional OptionalCommentNoSpace string `json:"optionalCommentNoSpace"` // Something before // // +optional // // Something after OptionalCommentExtra string `json:"optionalCommentExtra"` // +optional= OptionalCommentTag string `json:"optionalCommentTag"` // +optional=some-value OptionalCommentTagValue string `json:"optionalCommentTagValue"` // some-prefix+optional RequiredCommentPrefix string `json:"requiredCommentPrefix"` // +optional-some-suffix RequiredCommentSuffix string `json:"requiredCommentSuffix"` } type Identifier string const ( internalIdentifier Identifier = "internal" ) const _ = true // appease linter var _ = internalIdentifier // Level gives an indication of the extent of stuff. type Level int const ( /* Block comment. Indented. Empty line before. */ Unknown Level = iota Low // Medium is neither High nor Low Medium High ) type Level2 Level const ( AnotherLevel1 Level2 = iota + 4 AnotherLevel2 ) type CustomJSON struct { } func (c *CustomJSON) MarshalJSON() ([]byte, error) { return nil, nil } type CustomYAML struct { } func (c CustomYAML) MarshalYAML() ([]byte, error) { return nil, nil } type localType int const ( localConst localType = 1 _ = localConst // silence linter ) type Inline struct { Kind string } type NoInline struct { Kind string } type Interface interface { Boomer() bool } -- pkg2/add.cue -- package pkgtwo Barzer: { S: =~"cat$" } -- pkg2/pkg2.go -- // Package pkgtwo does other stuff. package pkgtwo import ( "math/big" t "time" ) // A Barzer barzes. type Barzer struct { A int `protobuf:"varint,2," json:"a"` T t.Time B *big.Int C big.Int F big.Float `xml:",attr"` G *big.Float H bool `json:"-"` S string XY bool `json:"x-y"` Err error *Inline `json:",inline"` } const Perm = 0755 const Few = 3 const Couple int = 2 // LongStringConst ensures that we are using go/constant // correctly for the exact value of a constant as opposed // to a shortened version (relevant for strings) const LongStringConst = "This is a really long string. Why are we using a long string? Because that way it ensures we are using go/constant.Value.ExactString() instead of go/constant.Value.String()" type Inline struct{ A int } -- pkg3/pkg3.go -- package pkg3 import pkgtwo "mod.test/pkg2" type Barzer = pkgtwo.Barzer -- pkg1/alias_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg1 package pkg1 import "mod.test/pkg2" #MyBarzer: pkgtwo.#Barzer -- pkg1/file1_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg1 // block comment package pkg1 import ( "time" p2 "mod.test/pkg2:pkgtwo" ) // Foozer foozes a jaman. #Foozer: { Int: int String: string #Inline NoInline: #NoInline CustomJSON: #CustomJSON CustomYAML?: null | #CustomYAML @go(,*CustomYAML) AnyJSON: _ @go(,json.Marshaler) AnyText: string @go(,encoding.TextMarshaler) bar?: int & >10 @go(Bar) Ptr: uint64 @go(,uintptr) UnsafePointer: uint64 @go(,unsafe.Pointer) Complex64: _ @go(,complex64) Complex128: _ @go(,complex128) Byte: uint8 @go(,byte) // Time is mapped to CUE's internal type. Time: time.Time Barzer: p2.#Barzer Alias1?: null | p2.#Barzer @go(,*MyBarzer) EmbedAliasInline: { p2.#Barzer } @go(,"struct{MyBarzer \"json:\\\",inline\\\"\"}") SliceAlias: [...p2.#Barzer] @go(,[]MyBarzer) // Note: Go encodings of protobuf tags are lossy. So this is a best-effort // thing. Map: {[string]: null | #CustomJSON} @go(,map[string]*CustomJSON) @protobuf(1,map[bytes]bytes,name=intf) Slice1: [...int] @go(,[]int) Slice2: [...] @go(,[]interface{}) Slice3?: null | [...] @go(,*[]json.Unmarshaler) Array1: 5 * [int] @go(,[5]int) Array2: 5 * [_] @go(,[5]interface{}) Array3?: null | 5*[_] @go(,*[5]json.Marshaler) Array4: bytes @go(,[5]byte) Intf: #Interface @protobuf(2,varint,name=intf) Intf2: _ @go(,interface{}) Intf3: { Interface: #Interface } @go(,struct{Interface}) Intf4: _ @go(,"interface{Foo()}") // Even though this struct as a type implements MarshalJSON, it is known // that it is really only implemented by the embedded field. Embed: { CustomJSON: #CustomJSON } @go(,struct{CustomJSON}) optionalOmitEmptyJSON?: string @go(OptionalOmitEmptyJSON) optionalOmitEmptyYAML?: string @go(OptionalOmitEmptyYAML) // +optional optionalComment?: string @go(OptionalComment) //+optional optionalCommentNoSpace?: string @go(OptionalCommentNoSpace) // Something before // // +optional // // Something after optionalCommentExtra?: string @go(OptionalCommentExtra) // +optional= optionalCommentTag?: string @go(OptionalCommentTag) // +optional=some-value optionalCommentTagValue?: string @go(OptionalCommentTagValue) // some-prefix+optional requiredCommentPrefix: string @go(RequiredCommentPrefix) // +optional-some-suffix requiredCommentSuffix: string @go(RequiredCommentSuffix) } #Identifier: string // #enumIdentifier #enumIdentifier: _#internalIdentifier _#internalIdentifier: #Identifier & "internal" // Level gives an indication of the extent of stuff. #Level: int // #enumLevel #enumLevel: #Unknown | #Low | #Medium | #High #values_Level: { Unknown: #Unknown Low: #Low Medium: #Medium High: #High } // Block comment. // Indented. // // Empty line before. #Unknown: #Level & 0 #Low: #Level & 1 // Medium is neither High nor Low #Medium: #Level & 2 #High: #Level & 3 #Level2: #Level // #enumLevel2 #enumLevel2: #AnotherLevel1 | #AnotherLevel2 #values_Level2: { AnotherLevel1: #AnotherLevel1 AnotherLevel2: #AnotherLevel2 } #AnotherLevel1: #Level2 & 4 #AnotherLevel2: #Level2 & 5 #CustomJSON: _ #CustomYAML: {} _#localType: int _#localConst: _#localType & 1 #Inline: Kind: string #NoInline: Kind: string #Interface: _ -- pkg2/add_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg2 // Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pkgtwo Barzer: { S: =~"cat$" } -- pkg2/pkg2_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg2 // Package pkgtwo does other stuff. package pkgtwo import t "time" // A Barzer barzes. #Barzer: { a: int @go(A) @protobuf(2,varint,) T: t.Time B?: null | int @go(,*big.Int) C: int @go(,big.Int) F: string @go(,big.Float) @xml(,attr) G?: null | string @go(,*big.Float) S: string "x-y": bool @go(XY) Err: _ @go(,error) #Inline } #Perm: 0o755 #Few: 3 #Couple: int & 2 #LongStringConst: "This is a really long string. Why are we using a long string? Because that way it ensures we are using go/constant.Value.ExactString() instead of go/constant.Value.String()" #Inline: A: int -- pkg3/pkg3_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg3 package pkg3 import "mod.test/pkg2:pkgtwo" #Barzer: pkgtwo.#Barzer -- pkg4/pkg4.go -- package pkg4 import "unsafe" type A struct { UnsafePointer unsafe.Pointer } -- pkg4/pkg4_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg4 package pkg4 #A: { UnsafePointer: uint64 @go(,unsafe.Pointer) } -- pkg_generics/pkg_generics.go -- package pkg_generics type SomeUnionInterface interface { string | int | byte } type SomeStructAny[T any] struct { SomeField T } type SomeStructString[T string] struct { SomeField T } type SomeStructSomeInterface[T SomeUnionInterface] struct { SomeField T } type SomeStructMultipleTypeParameters[T string, Z ~int] struct { SomeField T SomeOtherField Z } type SomeStructComparable[T comparable] struct { SomeField T } type SomeInterfaceWithMethod interface { int Do() string } type SomeAlias = string type StructWithAlias[T SomeAlias] struct { SomeField T } type SomeType int type StructWithType[T SomeType] struct { SomeField T } -- pkg_generics/pkg_generics_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/pkg_generics package pkg_generics #SomeUnionInterface: string | int | uint8 #SomeStructAny: { SomeField: _ @go(,T) } #SomeStructString: { SomeField: string @go(,T) } #SomeStructSomeInterface: { SomeField: #SomeUnionInterface @go(,T) } #SomeStructMultipleTypeParameters: { SomeField: string @go(,T) SomeOtherField: int @go(,Z) } #SomeStructComparable: { SomeField: _ @go(,T) } #SomeInterfaceWithMethod: int #SomeAlias: string #StructWithAlias: { SomeField: string @go(,T) } #SomeType: int #StructWithType: { SomeField: #SomeType @go(,T) } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_unresolvable_package.txtar000066400000000000000000000003741474664451600304670ustar00rootroot00000000000000# Test that we get expected error when we ask cue get go to get # a Go package that cannot be resolved. ! exec cue get go k8s.io/api/apps/v1 stderr '\Qno required module provides package k8s.io/api/apps/v1' -- go.mod -- module mod.test/blah go 1.14 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/get_go_vendor.txtar000066400000000000000000000012061474664451600256030ustar00rootroot00000000000000# Issue 1607 exec cue get go --local ./x cmp x/x_go_gen.cue x_go_gen.cue.golden # Verify that all transitive dependencies were generated properly. # If any are missing, the evaluation would fail to load them. exec cue eval ./x -- go.mod -- module mod.test go 1.21 -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- x/x.go -- package x import "mod.test/y" type X = y.Y -- y/y.go -- package y import "mod.test/z" type Y = z.Z -- z/z.go -- package z type Z int -- x_go_gen.cue.golden -- // Code generated by cue get go. DO NOT EDIT. //cue:generate cue get go mod.test/x package x import "mod.test/z" #X: z.#Z cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/go_cmd.txtar000066400000000000000000000001621474664451600242120ustar00rootroot00000000000000# Basic sanity check that go command works as expected # within testscript tests go version stdout '^go version' cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/goproxytest.txtar000066400000000000000000000006431474664451600253750ustar00rootroot00000000000000# Basic test to ensure that the goproxytest instance used by various testscript # tests works as expected. go get externalmod.test/mixfiles go mod tidy cmp go.mod go.mod.golden -- go.mod -- module test go 1.14 -- main.go -- package main import ( "fmt" "externalmod.test/mixfiles" ) func main() { fmt.Println(mixfiles.Orange) } -- go.mod.golden -- module test go 1.14 require externalmod.test/mixfiles v1.0.0 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/help.txtar000066400000000000000000000061331474664451600237160ustar00rootroot00000000000000# Verify that the various forms of requesting the top-level help. exec cue cmp stdout stdout.golden exec cue help cmp stdout stdout.golden exec cue --help cmp stdout stdout.golden exec cue -h cmp stdout stdout.golden # Requesting help for commands and sub-commands. exec cue help mod stdout -count=1 'groups commands which operate on CUE modules' stdout -count=1 'publish *publish the current module to a registry$' exec cue mod --help stdout -count=1 'groups commands which operate on CUE modules' stdout -count=1 'publish *publish the current module to a registry$' exec cue help mod publish stdout -count=1 '^Publish the current module to an OCI registry\.' exec cue mod publish --help stdout -count=1 '^Publish the current module to an OCI registry\.' # Requesting additional help topics; the form without "help" is phased out. exec cue help filetypes stdout -count=1 '^The cue tools supports the following file types:$' ! exec cue filetypes ! stdout . stderr -count=1 '^unknown command' # Requesting help for missing commands and sub-commands fails and prints the help text. ! exec cue help missing ! stdout . stderr -count=1 'Unknown help topic: missing' stderr -count=1 '^Available Commands:$' ! exec cue help mod missing ! stdout . stderr -count=1 'Unknown help topic: mod missing' stderr -count=1 '^Available Commands:$' # Requesting the help text for the help command itself is a bit silly. # `cue help` already describes how to query help for commands or topics. # Fail even though technically "help" is a valid command, just a special one. ! exec cue help help stderr -count=1 'Unknown help topic: help' -- stdout.golden -- CUE makes it easy to validate data, write schemas, and ensure configurations align with policies. CUE works with a wide range of tools and formats that you're already using such as Go, JSON, YAML, OpenAPI, and JSON Schema. For more information and documentation, see: https://cuelang.org Available Commands: cmd run a user-defined workflow command completion Generate completion script def print consolidated definitions eval evaluate and print a configuration export output data in a standard format fix rewrite packages to latest standards fmt formats CUE configuration files get add non-CUE dependencies to the current module import convert other formats to CUE files login log into a CUE registry mod module maintenance trim remove superfluous fields version print CUE version vet validate data Use "cue help [command]" for more information about a command. Additional help topics: cue help commands user-defined commands cue help embed file embedding cue help environment environment variables cue help filetypes supported file types and qualifiers cue help flags common flags for composing packages cue help injection inject files or values into specific fields for a build cue help inputs package list, patterns, and files cue help modules module support cue help registryconfig module registry configuration cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/help_cmd.txtar000066400000000000000000000114111474664451600245340ustar00rootroot00000000000000! exec cue cmd ! stdout . cmp stderr cue-cmd.stderr exec cue help cmd cmp stdout cue-help-cmd.stdout exec cue help cmd hello cmp stdout cue-help-cmd-hello.stdout exec cue help cmd hello . cmp stdout cue-help-cmd-hello.stdout mkdir subdir cp task_tool.cue subdir exec cue help cmd hello ./subdir cmp stdout cue-help-cmd-hello.stdout ! exec cue help cmd missing stderr -count=1 'Unknown cmd command: missing' stderr -count=1 '^Available Commands:$' stderr -count=1 'hello *say hello to someone' -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- task_tool.cue -- package home import "tool/cli" // say hello to someone // // Usage: hello // // Hello can be used to say hello to the world. command: hello: { task: say: { cli.Print text: "Hello world!" } } // echo something back command: echo: { task: echo: { cli.Print text: "ECHO Echo echo..." } } -- cue-cmd.stderr -- cmd must be run as one of its subcommands Run 'cue help cmd' for known subcommands. -- cue-help-cmd.stdout -- cmd executes the named command for each of the named instances. Workflow commands define actions on instances. For example, they may specify how to upload a configuration to Kubernetes. Workflow commands are defined directly in tool files, which are regular CUE files within the same package with a filename ending in _tool.cue. These are typically defined at the module root so that they apply to all instances. Each command consists of one or more tasks. A task may, for example, load or write a file, consult a user on the command line, fetch a web page, and so on. Each task has inputs and outputs. Outputs are typically filled out by the task implementation as the task completes. Inputs of tasks my refer to outputs of other tasks. The cue tool does a static analysis of the configuration and only starts tasks that are fully specified. Upon completion of each task, cue rewrites the instance, filling in the completed task, and reevaluates which other tasks can now start, and so on until all tasks have completed. Available tasks can be found in the package documentation at https://pkg.go.dev/cuelang.org/go/pkg/tool?tab=subdirectories Examples: In this simple example, we define a workflow command called "hello", which declares a single task called "print" which uses "tool/exec.Run" to execute a shell command that echos output to the terminal: $ cat < hello_tool.cue package foo import "tool/exec" city: "Amsterdam" who: *"World" | string @tag(who) // Say hello! command: hello: { print: exec.Run & { cmd: "echo Hello \(who)! Welcome to \(city)." } } EOF We run the "hello" workflow command like this: $ cue cmd hello Hello World! Welcome to Amsterdam. $ cue cmd --inject who=Jan hello Hello Jan! Welcome to Amsterdam. In this example we declare the "prompted" workflow command which has four tasks. The first task prompts the user for a string input. The second task depends on the first, and echos the response back to the user with a friendly message. The third task pipes the output from the second to a file. The fourth task pipes the output from the second to standard output (i.e. it echos it again). package foo import ( "tool/cli" "tool/exec" "tool/file" ) city: "Amsterdam" // Say hello! command: prompter: { // save transcript to this file var: file: *"out.txt" | string @tag(file) ask: cli.Ask & { prompt: "What is your name?" response: string } // starts after ask echo: exec.Run & { cmd: ["echo", "Hello", ask.response + "!"] stdout: string // capture stdout } // starts after echo append: file.Append & { filename: var.file contents: echo.stdout } // also starts after echo print: cli.Print & { text: echo.stdout } } Run "cue help commands" for more details on tasks and workflow commands. Usage: cue cmd [inputs] [flags] cue cmd [command] Available Commands: echo echo something back hello say hello to someone Flags: -t, --inject stringArray set the value of a tagged field -T, --inject-vars inject system variables in tags (default true) Global Flags: -E, --all-errors print all available errors -i, --ignore proceed in the presence of errors -s, --simplify simplify output --trace trace computation -v, --verbose print information about progress Use "cue cmd [command] --help" for more information about a command. -- cue-help-cmd-hello.stdout -- Hello can be used to say hello to the world. Usage: cue cmd hello [flags] Global Flags: -E, --all-errors print all available errors -i, --ignore proceed in the presence of errors -s, --simplify simplify output --trace trace computation -v, --verbose print information about progress cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/help_cmd_flags.txtar000066400000000000000000000072251474664451600257200ustar00rootroot00000000000000exec cue cmd -h cmp stdout expect-stdout exec cue cmd --help cmp stdout expect-stdout -- cue.mod/module.cue -- -- task_tool.cue -- package home import "tool/cli" // say hello to someone command: hello: { task: say: { cli.Print text: "Hello world!" } } // echo something back command: echo: { task: echo: { cli.Print text: "ECHO Echo echo..." } } -- expect-stdout -- cmd executes the named command for each of the named instances. Workflow commands define actions on instances. For example, they may specify how to upload a configuration to Kubernetes. Workflow commands are defined directly in tool files, which are regular CUE files within the same package with a filename ending in _tool.cue. These are typically defined at the module root so that they apply to all instances. Each command consists of one or more tasks. A task may, for example, load or write a file, consult a user on the command line, fetch a web page, and so on. Each task has inputs and outputs. Outputs are typically filled out by the task implementation as the task completes. Inputs of tasks my refer to outputs of other tasks. The cue tool does a static analysis of the configuration and only starts tasks that are fully specified. Upon completion of each task, cue rewrites the instance, filling in the completed task, and reevaluates which other tasks can now start, and so on until all tasks have completed. Available tasks can be found in the package documentation at https://pkg.go.dev/cuelang.org/go/pkg/tool?tab=subdirectories Examples: In this simple example, we define a workflow command called "hello", which declares a single task called "print" which uses "tool/exec.Run" to execute a shell command that echos output to the terminal: $ cat < hello_tool.cue package foo import "tool/exec" city: "Amsterdam" who: *"World" | string @tag(who) // Say hello! command: hello: { print: exec.Run & { cmd: "echo Hello \(who)! Welcome to \(city)." } } EOF We run the "hello" workflow command like this: $ cue cmd hello Hello World! Welcome to Amsterdam. $ cue cmd --inject who=Jan hello Hello Jan! Welcome to Amsterdam. In this example we declare the "prompted" workflow command which has four tasks. The first task prompts the user for a string input. The second task depends on the first, and echos the response back to the user with a friendly message. The third task pipes the output from the second to a file. The fourth task pipes the output from the second to standard output (i.e. it echos it again). package foo import ( "tool/cli" "tool/exec" "tool/file" ) city: "Amsterdam" // Say hello! command: prompter: { // save transcript to this file var: file: *"out.txt" | string @tag(file) ask: cli.Ask & { prompt: "What is your name?" response: string } // starts after ask echo: exec.Run & { cmd: ["echo", "Hello", ask.response + "!"] stdout: string // capture stdout } // starts after echo append: file.Append & { filename: var.file contents: echo.stdout } // also starts after echo print: cli.Print & { text: echo.stdout } } Run "cue help commands" for more details on tasks and workflow commands. Usage: cue cmd [inputs] [flags] Flags: -h, --help help for cmd -t, --inject stringArray set the value of a tagged field -T, --inject-vars inject system variables in tags (default true) Global Flags: -E, --all-errors print all available errors -i, --ignore proceed in the presence of errors -s, --simplify simplify output --trace trace computation -v, --verbose print information about progress cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/help_doc.txtar000066400000000000000000000015151474664451600245420ustar00rootroot00000000000000# Print the data for the current package a yaml. exec cue export --out=yaml cmp stdout stdout-export # Print the string value of the name field as a string. exec cue export -e name --out=text cmp stdout expect-stdout # Write the string value of the name field to a txt file. exec cue export -e name -o=foo.txt cmp stdout-foo foo.txt # Write the string value of the name field to a file foo. exec cue export -e name -o=text:foo cmp stdout-foo foo # Interpret bar.cue and foo.yaml as OpenAPI data. # cue def openapi: bar.cue foo.yaml # Write a CUE package as openapi encoded as YAML, using # an alternate file extension. # cue def -o openapi+yaml:foo.openapi -- foo.cue -- package bar name: "foo" _D: int -- bar.cue -- 3 -- foo.yaml -- 3 -- stdout-export -- name: foo -- stdout-foo -- foo -- stdout-name -- "foo" -- expect-stdout -- foo cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/help_registryconfig.txtar000066400000000000000000000150321474664451600270320ustar00rootroot00000000000000# Make sure that the registryconfig topic looks OK exec cue help registryconfig cmp stdout stdout.golden -- stdout.golden -- The registry configuration determines how CUE maps modules to their locations in OCI registries. Given a particular registry configuration, it's possible to work what registry a given module is stored in, and what repository within that registry, without making any network calls. If no explicit registry configuration is present, a default Central Registry (registry.cue.works) is used for all modules. The simplest way of specifying a registry configuration is to set $CUE_REGISTRY to the hostname of that registry. Examples: CUE_REGISTRY=myregistry.example CUE_REGISTRY=localhost:5000 CUE_REGISTRY='[::1]:5000' The special name "none" can be used to indicate that no registry should be used. If a path is present too, all modules will be stored under that path. For example: CUE_REGISTRY=localhost:5000/all/modules/will/be/stored/here By default for hosts other than localhost, a secure (HTTPS) connection will be used. This default can be set by appending "+insecure" or "+secure". For example: CUE_REGISTRY=100.98.141.117:5000+insecure CUE_REGISTRY=localhost:5000/modules+secure When specified in this way, the registry is used to fetch all modules. To use a specific registry for only certain subsets of modules, a prefix can be specified. This constrains a registry to be used only for modules that match that prefix. If there are multiple registries with a prefix, the longest matching prefix wins. When matching a prefix, only complete path elements (non-slash characters) are considered. It's an error if there are two identical prefixes in the same registry configuration. For example: CUE_REGISTRY='foo.example/bar=localhost:5000,myregistry.example' In the above example, modules with the prefix "foo.example/bar", such as "foo.example/bar/somemodule" (but not "foo.example/barry"), will be fetched from the registry at localhost:5000. All other modules will be fetched from "myregistry.example". Note that the syntax above implies that the ordering of the elements in CUE_REGISTRY isn't important because the resolution algorithm is order-independent. To specify that no registry should be used for a given module prefix, the special name "none" can be used. For example: CUE_REGISTRY='foo.example/bar=none,myregistry.example' In the above example, any attempt to fetch a module under "foo.example/bar" will result in a failure. Note that this will not take effect if the module is already present in the on-disk cache, which is consulted before looking at CUE_REGISTRY. Customizing Name Resolution Some registries have restrictions on what repositories can be used. For example, a registry implementation might restrict the depth of the available repository paths, or might even provide access to a single repository only. In order to accommodate these kinds of limitation, a registry configuration can also be specified in CUE syntax, usually as a configuration file. To do this, set CUE_REGISTRY to "file:" followed by the path to the configuration file. For example: CUE_REGISTRY=file:/home/alice/.config/cue/registry.cue To remove ambiguity, the simpler syntax described earlier can be explicitly requested with the "simple:" prefix. For example: CUE_REGISTRY=simple:myregistry.example If it is preferable not to create a file on disk for the configuration, the "inline:" prefix can be used: CUE_REGISTRY='inline:defaultRegistry: registry: "myregistry.example"' The configuration file syntax is described by the following CUE #file schema definition: // #file represents the registry configuration schema. #file: { // moduleRegistries specifies a mapping from module path prefix // (excluding any version suffix) to the registry to be used for // all modules under that path. // // A prefix is considered to match if a non-zero number of // initial path elements (sequences of non-slash characters) in // a module path match the prefix. // // If there are multiple matching prefixes, the longest // is chosen. moduleRegistries?: [#modulePath]: #registry // defaultRegistry specifies a fallback registry to be used if no // prefix from moduleRegistry matches. // If it's not present, a system default will be used. defaultRegistry?: #registry } #registry: { // registry specifies the registry host name and optionally, the // repository prefix to use for all modules in the repository, // and the security to use when accessing the host. // // It is in the form: // hostname[:port][/repoPrefix][+insecure] // // The hostname must be specified in square brackets if it's an // IPv6 address. // // Connections will be secure unless explicitly specified // otherwise, except for localhost connections which default to // insecure. // // See the doc comment on pathEncoding for details as to how // repoPrefix is used to determine the repository to use for a // specific module. // // As a special case, the registry may be "none", indicating // that there is no registry for its associated modules. // If a module resolves to a "none" registry, the resolver // will return an error. // // Examples: // "localhost:1234" // "myregistry.example/my-modules+secure" // "none" registry!: string // pathEncoding specifies how module versions map to // repositories within a registry. // Possible values are: // - "path": the repository is used as a prefix to the unencoded // module path. The version of the module is used as a tag. // - "hashAsPath": the hex-encoded SHA256 hash of the path is // used as a suffix to the above repository value. The version // of the module is used as a tag. // - "hashAsTag": the repository is used as is: the hex-encoded // SHA256 hash of the path followed by a hyphen and the version // is used as a tag. pathEncoding?: "path" | "hashAsRepo" | "hashAsTag" // prefixForTags specifies an arbitrary prefix that's added to // all tags. This can be used to disambiguate tags when there // might be some possibility of confusion with tags in use for // other purposes. prefixForTags?: #tag // TODO we could encode the invariant below in CUE but that // would result in poor error messages. With an error builtin, // that could perhaps be improved. // stripPrefix specifies that the pattern prefix should be // stripped from the module path before using as a repository // path. This only applies when pathEncoding is "path". stripPrefix?: bool } // TODO more specific schemas below #modulePath: string #tag: string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/hidden.txtar000066400000000000000000000006361474664451600242230ustar00rootroot00000000000000exec cue eval pkg.cue -H cmp stdout expect-stdout exec cue eval -H cmp stdout expect-stdout exec cue eval file.cue -H cmp stdout expect-stdout -- pkg.cue -- package pkg _top: 1 a: _h0: int #foo: { _h1: string } { _h2: string } -- file.cue -- _top: 1 a: _h0: int #foo: { _h1: string } { _h2: string } -- expect-stdout -- _top: 1 a: { _h0: int } #foo: { _h1: string } _h2: string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_auto.txtar000066400000000000000000000021201474664451600253200ustar00rootroot00000000000000exec cue import -o - ./openapi.yaml cmp stdout expect-openapi # Issue #3214 exec cue import -o - -f ./import1.yaml cmp stdout expect-stdout1 -- import1.yaml -- a: # inline comment for a b: "value" # inline comment for b -- expect-stdout1 -- a: // inline comment for a { b: "value" // inline comment for b } -- expect-openapi -- // An OpenAPI file info: { title: *"An OpenAPI file" | string version: *"v1beta1" | string } #Bar: { foo!: #Foo ... } #Foo: { a!: int b!: int & <10 & >=0 ... } -- openapi.yaml -- openapi: 3.0.0 info: title: An OpenAPI file version: v1beta1 paths: {} components: schemas: Foo: type: object required: - a - b properties: a: type: integer b: type: integer minimum: 0 exclusiveMaximum: 10 Bar: type: object required: - foo properties: foo: $ref: '#/components/schemas/Foo' cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_binary.txtar000066400000000000000000000006551474664451600256470ustar00rootroot00000000000000exec cue import binary --ext crt . cmp x.cue out/expect.cue exec cue export bin.cue --out binary cmp stdout out/bin # TODO: txtarscript should distinguish final newline exec cue export str.cue --out binary cmp stdout out/str -- x.crt -- 1234 -- y.crt2 -- // Skip this file, wrong extension. -- bin.cue -- ''' foo ''' -- str.cue -- """ foo """ -- out/bin -- foo -- out/str -- foo -- out/expect.cue -- ''' 1234 ''' cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_context.txtar000066400000000000000000000013671474664451600260500ustar00rootroot00000000000000exec cue import -o - -f --with-context -l '"\(path.Ext(filename)):\(index+1)/\(recordCount)": "\(data["@name"])":' ./import cmp stdout expect-stdout exec cue import -o - -f --with-context -l '"\(path.Ext(filename)):\(index+1)/\(recordCount)"' -l 'data["@name"]' ./import cmp stdout expect-stdout -- expect-stdout -- ".jsonl:1/3": elem1: { kind: "Service" "@name": "elem1" } ".jsonl:2/3": elem2: { kind: "Deployment" "@name": "elem2" } ".jsonl:3/3": elem3: { kind: "Service" "@name": "elem3" } -- import/services.jsonl -- { "kind": "Service", "@name": "elem1" } { "kind": "Deployment", "@name": "elem2" } { "kind": "Service", "@name": "elem3" } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_dir.txtar000066400000000000000000000001551474664451600251340ustar00rootroot00000000000000exec cue import -p foo ./... cmp x.cue expect.cue -- x.yml -- x: yyy -- expect.cue -- package foo x: "yyy" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_files.txtar000066400000000000000000000010331474664451600254540ustar00rootroot00000000000000exec cue import -o - -f --files ./import cmp stdout expect-stdout -- expect-stdout -- kind: "Service" name: "booster" kind: "Deployment" name: "booster" replicas: 1 kind: "Service" name: """ supplement foo """ json: "[1, 2]" -- import/services.jsonl -- { "kind": "Service", "name": "booster" } { "kind": "Deployment", "name": "booster", "replicas": 1 } { "kind": "Service", "name": "supplement\nfoo", "json": "[1, 2]" } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_hoiststr.txtar000066400000000000000000000021151474664451600262330ustar00rootroot00000000000000exec cue import -o - --recursive ./import/data.json cmp stdout expect-stdout -- expect-stdout -- import ( "encoding/json" "encoding/yaml" ) foo: { name: "something" json1: json.Marshal(_cue_json1) let _cue_json1 = [1, 2] json2: json.Marshal(_cue_json2) let _cue_json2 = { key: "value" } yaml1: yaml.Marshal(_cue_yaml1) let _cue_yaml1 = { a: "b" c: "d" } yaml2: yaml.Marshal(_cue_yaml2) let _cue_yaml2 = [ "one", "two", ] nocodec1: "\"str\"" nocodec2: "1234" nocodec3: "null" nocodec4: "true" nocodec5: "[a-z]+" nocodec6: "a: 123" nocodec7: "[a-z]+" nocodec8: "[a]" nocodec9: "{a: 1, b: 2}" } -- import/data.json -- { "foo": { "name": "something", "json1": "[1, 2]", "json2": "{\"key\": \"value\"}", "yaml1": "a: b\nc: d", "yaml2": "- one\n- two", "nocodec1": "\"str\"", "nocodec2": "1234", "nocodec3": "null", "nocodec4": "true", "nocodec5": "[a-z]+", "nocodec6": "a: 123", "nocodec7": "[a-z]+", "nocodec8": "[a]", "nocodec9": "{a: 1, b: 2}" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_list.txtar000066400000000000000000000022061474664451600253300ustar00rootroot00000000000000exec cue import -o - -f -l "\(strings.ToLower(kind))" --list ./import1 cmp stdout expect-stdout1 # Issue #368 exec cue import -o - -f --list ./import2 cmp stdout expect-stdout2 # Issue #369 exec cue import --with-context -l '"\(path.Ext(filename))": data' ./import3/data.json cmpenv import3/data.cue expect3 # Issue #2721 exec cue import -f --list issue2721/empty.yaml cmp issue2721/empty.cue issue2721/empty.cue.golden -- expect-stdout1 -- service: [{ kind: "Service" name: "booster" }, { kind: "Service" name: """ supplement foo """ json: "[1, 2]" }] deployment: [{ kind: "Deployment" name: "booster" replicas: 1 }] -- expect-stdout2 -- [[{a: 1}], [{b: 2}]] -- expect3 -- ".json": [1] -- import1/services.jsonl -- { "kind": "Service", "name": "booster" } { "kind": "Deployment", "name": "booster", "replicas": 1 } { "kind": "Service", "name": "supplement\nfoo", "json": "[1, 2]" } -- import2/data.jsonl -- [{"a": 1}] [{"b": 2}] -- import3/data.json -- [1] -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- issue2721/empty.yaml -- -- issue2721/empty.cue.golden -- [null] cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_match.txtar000066400000000000000000000003471474664451600254550ustar00rootroot00000000000000exec cue import -p uni --with-context -l 'path.Ext(filename)' -n '.*uni.yml' ./... cmp uni.cue out/expect-uni.cue -- uni.yml -- hello: world -- service.yaml -- x: foobie -- out/expect-uni.cue -- package uni ".yml": hello: "world" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_merge.txtar000066400000000000000000000004511474664451600254540ustar00rootroot00000000000000exec cue import -o - x.yaml -l objects: -l metadata.name cmp stdout expect-stdout -- x.yaml -- kind: "foo" metadata: name: foo --- kind: "foo" metadata: name: bar -- expect-stdout -- objects: foo: { kind: "foo" metadata: name: "foo" } objects: bar: { kind: "foo" metadata: name: "bar" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_path.txtar000066400000000000000000000013671474664451600253200ustar00rootroot00000000000000exec cue import -o - -f -l '"\(strings.ToLower(kind))": "\(name)":' ./import cmp stdout expect-stdout exec cue import -o - -f -l 'strings.ToLower(kind)' -l name ./import cmp stdout expect-stdout -- expect-stdout -- service: booster: { kind: "Service" name: "booster" } deployment: booster: { kind: "Deployment" name: "booster" replicas: 1 } service: "supplement\nfoo": { kind: "Service" name: """ supplement foo """ json: "[1, 2]" } -- import/services.jsonl -- { "kind": "Service", "name": "booster" } { "kind": "Deployment", "name": "booster", "replicas": 1 } { "kind": "Service", "name": "supplement\nfoo", "json": "[1, 2]" } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_proto.txtar000066400000000000000000000157771474664451600255410ustar00rootroot00000000000000cd root exec cue import proto -I ../include ./... cd .. cmp stderr expect-stderr cmp stdout expect-stdout cmp root/mixer/v1/attributes_proto_gen.cue expect-attributes_proto_gen.cue cmp root/mixer/v1/config/client/client_config_proto_gen.cue expect-client_config_proto_gen.cue cmp root/cue.mod/gen/googleapis.com/acme/test/test_proto_gen.cue expect-test_proto_gen.cue -- expect-stdout -- -- expect-stderr -- Skipping file "cue.mod/gen/googleapis.com/acme/test/test/test_proto_gen.cue": already exists. Use -Rf to override. -- root/cue.mod/module.cue -- module: "acme.test/api" language: version: "v0.9.0" -- root/cue.mod/gen/googleapis.com/acme/test/test/test_proto_gen.cue -- package test_test #AnotherTest: { test?: int32 @protobuf(1) } -- root/mixer/v1/attributes.proto -- syntax = "proto3"; import "google/protobuf/timestamp.proto"; import "acme/test.proto"; import "acme/test/test.proto"; package acme.mixer.v1; option go_package = "acme.test/api/mixer/v1"; // Attributes defines attributes. message Attributes { enum Type { TYPE_A = 1; TYPE_B = 2; } // A map of attribute name to its value. map attributes = 1; // Specifies one attribute value with different type. message AttributeValue { // The attribute value. oneof value { string string_value = 2; int64 int64_value = 3; double double_value = 4; bool bool_value = 5; bytes bytes_value = 6; google.protobuf.Timestamp timestamp_value = 7; // Used for values of type STRING_MAP StringMap string_map_value = 9; acme.test.Test test_value = 10; acme.test.test.AnotherTest test_value = 11; } } // Defines a string map. message StringMap { // Holds a set of name/value pairs. map entries = 1; } } -- root/mixer/v1/config/client/client_config.proto -- syntax = "proto3"; import "mixer/v1/attributes.proto"; // Describes the configuration state for the Mixer client library that's built into Envoy. package acme.mixer.v1.config.client; option go_package = "acme.test/api/mixer/v1/config/client"; // Defines the per-service client configuration. message ServiceConfig { bool disable_check_calls = 1; bool disable_report_calls = 2; Attributes mixer_attributes = 3; } -- include/acme/test.proto -- syntax = "proto3"; package acme.test; message Test { int32 test = 1; } -- include/acme/test/test.proto -- syntax = "proto3"; package acme.test.test; // Override the short name only of this package. This notation is seen in some // gogoproto files. option go_package = "test_test" message AnotherTest { int32 test = 1; } -- include/google/protobuf/timestamp.proto -- // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; option go_package = "github.com/golang/protobuf/ptypes/timestamp"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; message Timestamp { // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. int64 seconds = 1; // Non-negative fractions of a second at nanosecond resolution. Negative // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. int32 nanos = 2; } -- expect-attributes_proto_gen.cue -- package v1 import ( "time" "googleapis.com/acme/test" "googleapis.com/acme/test/test:test_test" ) // Attributes defines attributes. #Attributes: { #Type: #TYPE_A | #TYPE_B #TYPE_A: 1 #TYPE_B: 2 #Type_value: { TYPE_A: 1 TYPE_B: 2 } // A map of attribute name to its value. attributes?: { [string]: #AttributeValue } @protobuf(1,map[string]AttributeValue) // Specifies one attribute value with different type. #AttributeValue: { // The attribute value. {} | { stringValue: string @protobuf(2,string,name=string_value) } | { int64Value: int64 @protobuf(3,int64,name=int64_value) } | { doubleValue: float64 @protobuf(4,double,name=double_value) } | { boolValue: bool @protobuf(5,bool,name=bool_value) } | { bytesValue: bytes @protobuf(6,bytes,name=bytes_value) } | { timestampValue: time.Time @protobuf(7,google.protobuf.Timestamp,name=timestamp_value) } | { // Used for values of type STRING_MAP stringMapValue: #StringMap @protobuf(9,StringMap,name=string_map_value) } | { testValue: test.#Test @protobuf(10,acme.test.Test,name=test_value) } | { testValue: test_test.#AnotherTest @protobuf(11,acme.test.test.AnotherTest,name=test_value) } } // Defines a string map. #StringMap: { // Holds a set of name/value pairs. entries?: { [string]: string } @protobuf(1,map[string]string) } } -- expect-client_config_proto_gen.cue -- // Describes the configuration state for the Mixer client library that's built into Envoy. package client import "acme.test/api/mixer/v1" // Defines the per-service client configuration. #ServiceConfig: { disableCheckCalls?: bool @protobuf(1,bool,name=disable_check_calls) disableReportCalls?: bool @protobuf(2,bool,name=disable_report_calls) mixerAttributes?: v1.#Attributes @protobuf(3,Attributes,name=mixer_attributes) } -- expect-test_proto_gen.cue -- package test #Test: { test?: int32 @protobuf(1,int32) } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/import_proto2.txtar000066400000000000000000000160321474664451600256040ustar00rootroot00000000000000cd root exec cue import proto -I ../include ./... --proto_enum=json cd .. cmp stderr expect-stderr cmp stdout expect-stdout cmp root/mixer/v1/attributes_proto_gen.cue expect-attributes_proto_gen.cue cmp root/mixer/v1/config/client/client_config_proto_gen.cue expect-client_config_proto_gen.cue cmp root/cue.mod/gen/googleapis.com/acme/test/test_proto_gen.cue expect-test_proto_gen.cue -- expect-stdout -- -- expect-stderr -- Skipping file "cue.mod/gen/googleapis.com/acme/test/test/test_proto_gen.cue": already exists. Use -Rf to override. -- root/cue.mod/module.cue -- module: "acme.test/api" language: version: "v0.9.0" -- root/cue.mod/gen/googleapis.com/acme/test/test/test_proto_gen.cue -- package test_test #AnotherTest: { test?: int32 @protobuf(1) } -- root/mixer/v1/attributes.proto -- syntax = "proto3"; import "google/protobuf/timestamp.proto"; import "acme/test.proto"; import "acme/test/test.proto"; package acme.mixer.v1; option go_package = "acme.test/api/mixer/v1"; // Attributes defines attributes. message Attributes { enum Type { TYPE_A = 1; TYPE_B = 2; } // A map of attribute name to its value. map attributes = 1; // Specifies one attribute value with different type. message AttributeValue { // The attribute value. oneof value { string string_value = 2; int64 int64_value = 3; double double_value = 4; bool bool_value = 5; bytes bytes_value = 6; google.protobuf.Timestamp timestamp_value = 7; // Used for values of type STRING_MAP StringMap string_map_value = 9; acme.test.Test test_value = 10; acme.test.test.AnotherTest test_value = 11; } } // Defines a string map. message StringMap { // Holds a set of name/value pairs. map entries = 1; } } -- root/mixer/v1/config/client/client_config.proto -- syntax = "proto3"; import "mixer/v1/attributes.proto"; // Describes the configuration state for the Mixer client library that's built into Envoy. package acme.mixer.v1.config.client; option go_package = "acme.test/api/mixer/v1/config/client"; // Defines the per-service client configuration. message ServiceConfig { bool disable_check_calls = 1; bool disable_report_calls = 2; Attributes mixer_attributes = 3; } -- include/acme/test.proto -- syntax = "proto3"; package acme.test; message Test { int32 test = 1; } -- include/acme/test/test.proto -- syntax = "proto3"; package acme.test.test; // Override the short name only of this package. This notation is seen in some // gogoproto files. option go_package = "test_test" message AnotherTest { int32 test = 1; } -- include/google/protobuf/timestamp.proto -- // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; option go_package = "github.com/golang/protobuf/ptypes/timestamp"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; message Timestamp { // Represents seconds of UTC time since Unix epoch // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to // 9999-12-31T23:59:59Z inclusive. int64 seconds = 1; // Non-negative fractions of a second at nanosecond resolution. Negative // second values with fractions must still have non-negative nanos values // that count forward in time. Must be from 0 to 999,999,999 // inclusive. int32 nanos = 2; } -- expect-attributes_proto_gen.cue -- package v1 import ( "time" "googleapis.com/acme/test" "googleapis.com/acme/test/test:test_test" ) // Attributes defines attributes. #Attributes: { #Type: {"TYPE_A", #enumValue: 1} | {"TYPE_B", #enumValue: 2} #Type_value: { TYPE_A: 1 TYPE_B: 2 } // A map of attribute name to its value. attributes?: { [string]: #AttributeValue } @protobuf(1,map[string]AttributeValue) // Specifies one attribute value with different type. #AttributeValue: { // The attribute value. {} | { stringValue: string @protobuf(2,string,name=string_value) } | { int64Value: int64 @protobuf(3,int64,name=int64_value) } | { doubleValue: float64 @protobuf(4,double,name=double_value) } | { boolValue: bool @protobuf(5,bool,name=bool_value) } | { bytesValue: bytes @protobuf(6,bytes,name=bytes_value) } | { timestampValue: time.Time @protobuf(7,google.protobuf.Timestamp,name=timestamp_value) } | { // Used for values of type STRING_MAP stringMapValue: #StringMap @protobuf(9,StringMap,name=string_map_value) } | { testValue: test.#Test @protobuf(10,acme.test.Test,name=test_value) } | { testValue: test_test.#AnotherTest @protobuf(11,acme.test.test.AnotherTest,name=test_value) } } // Defines a string map. #StringMap: { // Holds a set of name/value pairs. entries?: { [string]: string } @protobuf(1,map[string]string) } } -- expect-client_config_proto_gen.cue -- // Describes the configuration state for the Mixer client library that's built into Envoy. package client import "acme.test/api/mixer/v1" // Defines the per-service client configuration. #ServiceConfig: { disableCheckCalls?: bool @protobuf(1,bool,name=disable_check_calls) disableReportCalls?: bool @protobuf(2,bool,name=disable_report_calls) mixerAttributes?: v1.#Attributes @protobuf(3,Attributes,name=mixer_attributes) } -- expect-test_proto_gen.cue -- package test #Test: { test?: int32 @protobuf(1,int32) } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/inject.txtar000066400000000000000000000021671474664451600242450ustar00rootroot00000000000000exec cue eval test.cue -t env=prod cmp stdout expect-stdout exec cue eval vars.cue -T cmp stdout expect-stdout-vars exec cue eval vars.cue -T -t dir=xxx cmp stdout expect-stdout-override exec cue eval vars.cue cmp stdout expect-stdout-novars ! exec cue eval -T err.cue cmp stderr expect-stderr-err exec cue cmd user vars.cue vars_tool.cue cmp stdout expect-stdout-tool # TODO: report errors for invalid tags? -- test.cue -- { environment: "prod" | "staging" @tag(env,short=prod|staging) } -- expect-stdout -- environment: "prod" -- vars.cue -- import "path" _os: string @tag(os,var=os) _dir: string @tag(dir,var=cwd) base: path.Base(_dir, _os) -- err.cue -- dir: string @tag(dir,var=userz) -- vars_tool.cue -- import ( "path" "tool/cli" ) wd: string @tag(wd,var=cwd) _os: string @tag(os,var=os) command: user: { base: cli.Print & { text: path.Base(wd, _os) } } -- expect-stdout-vars -- base: "script-inject" -- expect-stderr-err -- tag variable 'userz' not found -- expect-stdout-override -- base: "xxx" -- expect-stdout-novars -- import "path" base: path.Base(_dir, _os) -- expect-stdout-tool -- script-inject cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/injecterr.txtar000066400000000000000000000013711474664451600247520ustar00rootroot00000000000000! exec cue eval test.cue -t env=prod cmp stderr expect-stderr # TODO: report errors for invalid tags? -- test.cue -- { environment: "prod" | "staging" @tag(env,short=prod|staging) // Don't replace in optional opt?: string @tag(env) bulk: [string]: foo: string @tag(env) bulk: x: {} // Don't replace in lists. a: [ { no_replace: string @tag(env) } ] // Don't allow in comprehensions src: [1, 2] for _ in src { b: string @tag(prod) } } -- expect-stderr -- @tag not allowed within field constraint: ./test.cue:5:18 @tag not allowed within field constraint: ./test.cue:6:33 @tag not allowed within lists: ./test.cue:11:30 @tag not allowed within comprehension: ./test.cue:17:19 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/invalid_tag_pos.txtar000066400000000000000000000016171474664451600261320ustar00rootroot00000000000000exec cue def jsonschema: schema.json cmp stdout expect-stdout -- schema.json -- { "$id": "https://2.test.example/object ", "type": "object", "additionalProperties": false } -- expect-stdout -- close({ @jsonschema(id="https://2.test.example/object%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20") }) cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue-2945-with-modules.txtar000066400000000000000000000013061474664451600271330ustar00rootroot00000000000000# Root package cannot work ! exec cue export mod.example stderr 'unknown file extension \.example' # Explicitly select root package to resolve ambiguity exec cue export mod.example:x cmp stdout root.golden # p implicitly selected exec cue export mod.example/p cmp stdout p.golden # p explicitly selected exec cue export mod.example/p:p cmp stdout p.golden # with fully qualified import path exec cue export mod.example/p@v0:p cmp stdout p.golden # as relative path exec cue export ./p cmp stdout p.golden -- cue.mod/module.cue -- module: "mod.example@v0" language: version: "v0.8.0" -- x.cue -- package x x: 5 -- p/p.cue -- package p p: 4 -- root.golden -- { "x": 5 } -- p.golden -- { "p": 4 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue-2945.txtar000066400000000000000000000011251474664451600245130ustar00rootroot00000000000000# Root package cannot work ! exec cue export mod.example stderr 'unknown file extension \.example' # Explicitly select root package to resolve ambiguity exec cue export mod.example:x cmp stdout root.golden # p implicitly selected exec cue export mod.example/p cmp stdout p.golden # p explicitly selected exec cue export mod.example/p:p cmp stdout p.golden exec cue export ./p cmp stdout p.golden -- cue.mod/module.cue -- module: "mod.example" language: version: "v0.9.0" -- x.cue -- package x x: 5 -- p/p.cue -- package p p: 4 -- root.golden -- { "x": 5 } -- p.golden -- { "p": 4 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue116.txtar000066400000000000000000000005731474664451600243500ustar00rootroot00000000000000stdin in exec cue import yaml: - cmp stdout stdout-cue1 stdin in exec cue export yaml: - cmp stdout stdout-json stdin in exec cue eval yaml: - cmp stdout stdout-cue2 stdin in exec cue def yaml: - cmp stdout stdout-cue3 -- in -- foo: bar -- stdout-cue1 -- foo: "bar" -- stdout-cue2 -- foo: "bar" -- stdout-cue3 -- foo: "bar" -- stdout-json -- { "foo": "bar" } -- dummy -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue1270.txtar000066400000000000000000000015071474664451600244300ustar00rootroot00000000000000exec cue def test.cue test.json -o openapi:- -e '{#Output: #Test}' cmp stdout stdout.golden -- test.cue -- #Int: int #Test: test: #Int -- test.json -- { } -- stdout.golden -- { "openapi": "3.0.0", "info": { "title": "Generated by cue.", "version": "no version" }, "paths": {}, "components": { "schemas": { "Int": { "type": "integer" }, "Output": { "$ref": "#/components/schemas/Test" }, "Test": { "type": "object", "required": [ "test" ], "properties": { "test": { "$ref": "#/components/schemas/Int" } } } } } }cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue174.txtar000066400000000000000000000005661474664451600243560ustar00rootroot00000000000000! exec cue export ./issue174 cmp stderr expect-stderr # TODO(mvdan): the filename below lacks the common "./" prefix from other errors. -- expect-stderr -- build constraints exclude all CUE files in ./issue174: issue174/issue174.cue: no package name -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- issue174/issue174.cue -- import 'foo' a: 1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue217.txtar000066400000000000000000000004261474664451600243470ustar00rootroot00000000000000exec cue eval cmp stdout eval-stdout exec cue def cmp stdout def-stdout -- schema.cue -- package tst x: { a: #A b: #A } #A: string | [#A] -- def-stdout -- package tst x: { a: #A b: #A } #A: string | [#A] -- eval-stdout -- x: { a: string b: string } #A: string cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue2207.txtar000066400000000000000000000004211474664451600244230ustar00rootroot00000000000000exec cue vet data.yaml schema.cue exec cue vet data2.yaml schema2.cue exec cue vet data.yaml schema2.cue -d x -- data.yaml -- a: 200 -- schema.cue -- a: int if a > 100 { b: true } -- data2.yaml -- x: a: 200 -- schema2.cue -- x: { a: int if a > 100 { b: true } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue236.txtar000066400000000000000000000001601474664451600243430ustar00rootroot00000000000000exec cue trim -- in.cue -- package x #Schema: { optional: string } d: #Schema d: { optional: "some" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue269.txtar000066400000000000000000000007171474664451600243610ustar00rootroot00000000000000exec cue eval ./struct.cue cmp stderr expect-stderr cmp stdout expect-stdout -- struct.cue -- #type: { x: 0 y: 0 if x == 0 {i: 0} if y == 0 {j: 0} } data: { a: #type b: #type b: x: a.x a: y: b.y } -- expect-stderr -- -- expect-stdout -- #type: { x: 0 y: 0 i: 0 j: 0 } data: { a: { x: 0 y: 0 i: 0 j: 0 } b: { x: 0 y: 0 i: 0 j: 0 } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue289.txtar000066400000000000000000000005511474664451600243570ustar00rootroot00000000000000# TODO: error message could be improved. ! exec cue import test.yaml -p kube -l 'strings.ToCamel(kind)' -l metadata.name -f cmp stderr expect-stderr -- test.yaml -- apiVersion: v1 kind: Service metadata: name: ingress-nginx spec: type: NodePort --- # EMPTY FILE -- expect-stderr -- error evaluating label strings.ToCamel(kind): reference "kind" not found cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue2955.txtar000066400000000000000000000017131474664451600244420ustar00rootroot00000000000000# Test that cue mod tidy works even when a registry # responds with a 401 error instead of a 403 error. # This is exactly the same as registry_token_auth_tidy.txtar # except for the presence of the "always401" field # in auth.json. env DOCKER_CONFIG=$WORK/dockerconfig env-fill $DOCKER_CONFIG/config.json env CUE_DEBUG=http exec cue mod tidy exec cue export . cmp stdout expect-stdout -- dockerconfig/config.json -- { "auths": { "${DEBUG_REGISTRY_HOST}": { "identitytoken": "registrytest-refresh" } } } -- expect-stdout -- "ok" -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" -- _registry/auth.json -- { "useTokenServer": true, "acl": { "allow": ["^example\\.com/e$"] }, "always401": true } -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "ok" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue2964.txtar000066400000000000000000000002551474664451600244420ustar00rootroot00000000000000exec cue mod init test.example ! exec cue export anypath cmp stderr want-stderr -- want-stderr -- standard library import path "anypath" cannot be imported as a CUE package cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue302.txtar000066400000000000000000000002251474664451600243370ustar00rootroot00000000000000exec cue trim foo.cue cmp foo.cue rewritten -- foo.cue -- package p foo?: #Foo #Foo: "hello" -- rewritten -- package p foo?: #Foo #Foo: "hello"cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue303.txtar000066400000000000000000000002621474664451600243410ustar00rootroot00000000000000exec cue trim foo.cue cmp foo.cue rewritten -- foo.cue -- package example foo: c: true foo: #M #M: c?: bool -- rewritten -- package example foo: c: true foo: #M #M: c?: bool cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue304.txtar000066400000000000000000000003331474664451600243410ustar00rootroot00000000000000exec cue def -e '#Foo' x.cue cmp stdout expect-stdout -- expect-stdout -- _#def _#def: { x: int body?: { a: int b?: string } } -- x.cue -- package example #Foo: { x: int body?: { a: int b?: string } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue312.txtar000066400000000000000000000003571474664451600243460ustar00rootroot00000000000000! exec cue export x.cue -out cue cmp stderr expect-stderr ! exec cue export -out cue cmp stderr expect-stderr ! exec cue export -out x.cue cmp stderr expect-stderr -- expect-stderr -- no encoding specified for file "ut" -- x.cue -- a: 1cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3144.txtar000066400000000000000000000005501474664451600244270ustar00rootroot00000000000000# Check that unrelated invalid files do not cause an error when only files # are specified on the command line. exec cue export valid.cue cmp stdout stdout.golden -- stdout.golden -- { "out": "bar" } -- cue.mod/module.cue -- module: "foo.test/bar" language: version: "v0.9.0" -- valid.cue -- #foo: "bar" out: #foo -- invalid.cue -- foo :: "bar" out: foo cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3147.txtar000066400000000000000000000006741474664451600244410ustar00rootroot00000000000000# Check that imports from files specified on the command line # are still considered even when they are not part of the main module. exec cue export _foo/x.cue cmp stdout stdout.golden -- cue.mod/module.cue -- module: "mod.com@v0" language: { version: "v0.9.0" } -- cue.mod/pkg/example.com/banana/banana.cue -- package banana X: 42 -- _foo/x.cue -- package p import "example.com/banana" x: banana.X -- stdout.golden -- { "x": 42 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue315.txtar000066400000000000000000000004571474664451600243520ustar00rootroot00000000000000! exec cue vet -c file.cue cmp stderr expect-stderr -- expect-stderr -- invalid interpolation: non-concrete value string (type string): ./file.cue:12:1 ./file.cue:3:5 -- file.cue -- #X: { x: string y: string z: string } #X: { x: "x" z: "z" } """ hello world \(#X.x) \(#X.y) \(#X.z) """ cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue322.txtar000066400000000000000000000003041474664451600243370ustar00rootroot00000000000000! exec cue vet cmp stderr expect-stderr -- expect-stderr -- imported and not used: "strings": ./x.cue:2:8 -- x.cue -- package x import "strings" foo: "hello" -- y.cue -- package x bar: foocue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3228.txtar000066400000000000000000000010231474664451600244260ustar00rootroot00000000000000# This verifies that evaluation of build attributes is not order-dependent. ! exec cue export cmp stderr error exec cue export -t C cmp stdout out exec cue export -t A -t B cmp stdout out exec cue export -t A -t C cmp stdout out exec cue export -t B -t C cmp stdout out exec cue export -t A -t B -t C cmp stdout out -- example.cue -- @if( A && B || C ) package example x: 1 -- out -- { "x": 1 } -- error -- build constraints exclude all CUE files in .: script-issue3228/example.cue: @if( A && B || C ) did not match cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue324.txtar000066400000000000000000000003721474664451600243460ustar00rootroot00000000000000! exec cue vet foo.cue cmp stderr expect-stderr -- foo.cue -- import "encoding/yaml" x: string a: b: c: *["\(x)"] | _ d: yaml.Marshal(a.b) -- expect-stderr -- some instances are incomplete; use the -c flag to show errors or suppress this message cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3250.txtar000066400000000000000000000005711474664451600244300ustar00rootroot00000000000000# This checks that @if tags work for files specified on the command line. # passes - no module exec cue export -t foo .:foo exec cue export -t foo foo.cue # set up module exec cue mod init # passes - with module exec cue export -t foo .:foo # passes - with module # (failed previously due to #3250). exec cue export -t foo foo.cue -- foo.cue -- @if(foo) package foo x: 1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3281.txtar000066400000000000000000000005351474664451600244340ustar00rootroot00000000000000# When there's a syntax error encountered at an early # stage of processing, the error message should # point to the place in the file where the error was # encountered. ! exec cue eval invalid.cue stderr invalid.cue:3: -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- invalid.cue -- package blah self: bad ) syntax cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3282.txtar000066400000000000000000000010031474664451600244240ustar00rootroot00000000000000# Check that an imported package with bad syntax produces # a sane error (it did panic). ! exec cue export cmp stderr want-stderr -- want-stderr -- test.example@v0: import failed: cannot find package "test.example/blah": cannot get imports: cannot read "blah/invalid.cue": missing ',' in struct literal: ./foo.cue:2:8 -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- foo.cue -- package foo import "test.example/blah" blah -- blah/invalid.cue -- package blah self: bad ) syntax cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue3298.txtar000066400000000000000000000005461474664451600244460ustar00rootroot00000000000000[!unix] skip exec cp x/x.cue_actual x/x.cue exec cue export cmp stdout want-stdout rm x/x.cue exec ln -s x.cue_actual ./x/x.cue exec cue export . -- want-stdout -- { "self": "x" } -- cue.mod/module.cue -- module: "example.com" language: version: "v0.9.0" -- main.cue -- package main import "example.com/x" x -- x/x.cue_actual -- package x self: "x" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue398.txtar000066400000000000000000000005011474664451600243530ustar00rootroot00000000000000exec cue eval ./pkg:foo cmp stdout expect-stdout -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- pkg/foo.cue -- package foo import "mod.test/pkg:bar" bar z: 3 -- pkg/bar.cue -- package bar import "mod.test/pkg:baz" baz y: 2 -- pkg/baz.cue -- package baz x: 1 -- expect-stdout -- x: 1 y: 2 z: 3 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue425.txtar000066400000000000000000000001661474664451600243510ustar00rootroot00000000000000exec cue vet list.cue list.json cmp stdout expect-stdout -- list.cue -- [] -- list.json -- [] -- expect-stdout -- cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue461.txtar000066400000000000000000000006151474664451600243500ustar00rootroot00000000000000exec cue cmd writefile -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- expect-hello -- Hello, world! -- x_tool.cue -- package x import ( "strings" "tool/exec" "tool/file" ) command: writefile: { echo: exec.Run & { cmd: "echo hello.txt" stdout: string } write: file.Create & { filename: strings.TrimSpace(echo.stdout) contents: "Hello, world!" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue473.txtar000066400000000000000000000012351474664451600243520ustar00rootroot00000000000000exec cue eval --out json x.cue -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- x.cue -- package x #Guide: { Terminals: [string]: #Terminal Steps: [string]: #Step #TerminalName: or([for k, _ in Terminals {k}]) #Step: { Terminal: #TerminalName Cmd: string } #Terminal: { Image: string } } g: #Guide & { Terminals: client: { Image: "golang" } Steps: { list: { Terminal: "client" Cmd: "ls" } } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue476.txtar000066400000000000000000000010451474664451600243540ustar00rootroot00000000000000exec cue cmd dostuffloop cmp stdout expect-stdout -- x_tool.cue -- package x import ( "tool/cli" "encoding/yaml" ) command: dostuff: { write: cli.Print & { text: "yaml is " + yaml.Marshal(w) } } command: dostuffloop: { for w in l { write: cli.Print & { text: "yaml is " + yaml.Marshal(w) } } } -- y.cue -- package x #Workflow: { #: "working-directory": string } l: [w] w: #Workflow & { } -- expect-stdout -- yaml is {} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue477.txtar000066400000000000000000000003741474664451600243610ustar00rootroot00000000000000! exec cue cmd print cmp stderr expect-stderr -- x_tool.cue -- package x import ( "strings" "tool/cli" ) command: print: cli.Print & { text: "this is a test" } -- expect-stderr -- imported and not used: "strings": ./x_tool.cue:4:5 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue512.txtar000066400000000000000000000003641474664451600243460ustar00rootroot00000000000000exec cue export -o bools.yaml bools.cue exec cue import -o bools2.cue bools.yaml cmp bools.cue bools2.cue -- bools.cue -- x: [ "n", "N", "no", "No", "NO", "y", "Y", "yes", "Yes", "YES", "off", "Off", "OFF", "on", "On", "ON", ] cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue520.txtar000066400000000000000000000006751474664451600243520ustar00rootroot00000000000000exec cue cmd -t greeting=hello prefix -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- my.cue -- package tools msg: string @tag(greeting) -- my_tool.cue -- package tools import ( "tool/cli" ) greeting: string @tag(greeting) command: prefix: { p1: cli.Print & { text: greeting } salutation: string @tag(greeting) p2: cli.Print & { text: salutation } p3: cli.Print & { text: msg @tag(greeting) } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue525.txtar000066400000000000000000000005401474664451600243460ustar00rootroot00000000000000exec cue cmd gengithub -- x.cue -- package x test: #Workflow & { } #Workflow: { #: "working-directory": string } -- x_tool.cue -- package x import ( "tool/file" "encoding/yaml" ) command: gengithub: { write: file.Create & { filename: "test.yml" contents: """ # Generated by ci_tool.cue; do not edit \(yaml.Marshal(test)) """ } }cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue526.txtar000066400000000000000000000002131474664451600243440ustar00rootroot00000000000000exec cue cmd gengithub -- x.cue -- package x test: #Workflow #Workflow: 1 | [_] -- x_tool.cue -- package x command: gengithub: {} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue749.txtar000066400000000000000000000003711474664451600243600ustar00rootroot00000000000000exec cue eval ./float.cue cmp stderr expect-stderr cmp stdout expect-stdout -- float.cue -- import "strconv" x : strconv.ParseFloat("3.14", 32) y : strconv.ParseFloat("3.14", 64) -- expect-stderr -- -- expect-stdout -- x: 3.140000104904175 y: 3.14cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue826.txtar000066400000000000000000000011421474664451600243510ustar00rootroot00000000000000exec cue import x.yaml cmp x.cue expect.cue -- x.yaml -- # Importing YAML with multi-byte characters as CUE resulted in bad formatting # since the YAML decoder would count columns by characters and we count by bytes. x1: # ああああああああああああああああああ description: ああ type: string -- expect.cue -- // Importing YAML with multi-byte characters as CUE resulted in bad formatting // since the YAML decoder would count columns by characters and we count by bytes. x1: { // ああああああああああああああああああ description: "ああ" type: "string" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/issue986.txtar000066400000000000000000000007401474664451600243630ustar00rootroot00000000000000 # Hidden values are dropped when outputting CUE. This is fine in eval for # debugging, but not when the final result needs to be compiled again to be # converted to another format. exec cue eval in.cue --out yaml cmp stdout expect-stdout -- in.cue -- #Foo: { a: string b: string ab: "\(a)\(b)" } { a: "aaa" b: "bbb" } & #Foo #Bar: { _c: string _d: string cd: "\(_c)\(_d)" } { _c: "ccc" _d: "ddd" } & #Bar -- expect-stdout -- a: aaa b: bbb ab: aaabbb cd: cccddd cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/json_syntax_error.txtar000066400000000000000000000006651474664451600265620ustar00rootroot00000000000000! exec cue export x1.json stderr 'x1*.json:4:3' ! exec cue export x2.json stderr 'x2.json:1:6' ! exec cue export x3.json stderr 'x3.json:1:1' ! exec cue export x4.json stderr 'x4.json:1:1' ! exec cue export x5.jsonl stderr 'x5.jsonl:8:12' -- x1.json -- { "foo": true, "bar": 2 "baz": false } -- x2.json -- "baz": false -- x3.json -- baz: false -- x4.json -- -- x5.jsonl -- { "foo": true } { "bar": false } { "invalid": ] } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/load_pkg.txtar000066400000000000000000000050241474664451600245440ustar00rootroot00000000000000# mixing two anonymous packages exec cue eval t.cue data.cue cmp stdout stdout-t # allow mixing named with anonymous package in files mode exec cue eval kube.cue data.cue cmp stdout stdout-files # allow mixing named with anonymous package in files mode exec cue eval kube.cue data.cue t.cue cmp stdout stdout-files # don't pick up the unnamed package in directory mode exec cue eval . cmp stdout stdout-pkg # don't allow mixing two differently named packages ! exec cue eval kube.cue foo/kube2.cue # When passing multiple CUE files in different directories, # cue/load will sort the filenames so that children come later. # Due to a bug, we had an unstable sort that changed between Go 1.18 and 1.19. # Ensure that our sorting is deterministic with 8 scattered files. cd sort # First, test with the same input order that "find" would use: lexically sorted. exec cue eval print.cue root_1.cue root_2/child_1.cue root_2/child_2.cue root_2/child_3.cue root_2/child_4/grandchild_1.cue root_2/child_4/grandchild_2.cue root_2/child_5.cue root_2/child_6.cue root_2/child_7.cue root_3.cue cmp stdout stdout-sort # Second, test with the opposite order of what we want. exec cue eval print.cue root_2/child_4/grandchild_2.cue root_2/child_4/grandchild_1.cue root_2/child_7.cue root_2/child_6.cue root_2/child_5.cue root_2/child_3.cue root_2/child_2.cue root_2/child_1.cue root_3.cue root_1.cue cmp stdout stdout-sort cd .. -- data.cue -- foo:3 -- t.cue -- foo: int bar: 3 -- kube.cue -- package kube foo: int bar: 3 -- foo/kube2.cue -- package kube2 foo: int bar: 3 -- stdout-t -- foo: 3 bar: 3 -- stdout-files -- foo: 3 bar: 3 -- stdout-pkg -- foo: int bar: 3 -- sort/print.cue -- files: {} flat: [for k, _ in files {k}] -- sort/root_1.cue -- files: root_1: 0 -- sort/root_2/child_1.cue -- files: child_1: 0 -- sort/root_2/child_2.cue -- files: child_2: 0 -- sort/root_2/child_3.cue -- files: child_3: 0 -- sort/root_2/child_4/grandchild_1.cue -- files: grandchild_1: 0 -- sort/root_2/child_4/grandchild_2.cue -- files: grandchild_2: 0 -- sort/root_2/child_5.cue -- files: child_5: 0 -- sort/root_2/child_6.cue -- files: child_6: 0 -- sort/root_2/child_7.cue -- files: child_7: 0 -- sort/root_3.cue -- files: root_3: 0 -- sort/stdout-sort -- files: { child_1: 0 child_2: 0 child_3: 0 child_5: 0 child_6: 0 child_7: 0 grandchild_1: 0 grandchild_2: 0 root_1: 0 root_3: 0 } flat: ["root_1", "root_3", "child_1", "child_2", "child_3", "child_5", "child_6", "child_7", "grandchild_1", "grandchild_2"] cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/load_underscore.txtar000066400000000000000000000016601474664451600261360ustar00rootroot00000000000000# Test whether an import with a _ qualifer is allowed or not. ! exec cue export ./foo cmp stderr want-stderr # Check that it also fails with an explicit _ qualifier # specified on the command line ! exec cue export other.example/m:_ cmp stderr want-stderr-2 -- want-stderr -- test.example/foo/foo@v0: import failed: _ is not a valid import path qualifier in "other.example/m:_": ./foo/foo.cue:8:8 -- want-stderr-2 -- invalid import path qualifier _ in "other.example/m:_" -- cue.mod/gen/other.example/m/m.cue -- package _ x: 20 -- cue.mod/module.cue -- module: "test.example/foo" language: version: "v0.9.0" -- foo/foo.cue -- // Note: the package name does not match the directory name, // which means that this is only resolvable with an explicit // qualifier when used as an import path, but is allowed // on the cue command line because there's only one // package in the directory. package bar import m "other.example/m:_" x: m.x cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/load_with_unnamed_pkg.txtar000066400000000000000000000014371474664451600273120ustar00rootroot00000000000000# Test that the command-line "allow single package # even when the package name does not match the import # path" logic works correctly in the presence of an # non-package CUE file, which can never be part # of a package. cd foo exec cue export cmp stdout $WORK/want-stdout -- want-stdout -- { "x": 20 } -- cue.mod/gen/other.example/m/m.cue -- package m x: 20 -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- foo/foo.cue -- // Note: the package name does not match the directory name, // which means that this is only resolvable with an explicit // qualifier when used as an import path, but is allowed // on the cue command line because there's only one // package in the directory. package bar import "other.example/m" x: m.x -- foo/unnamed.cue -- import () cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/login_expired.txtar000066400000000000000000000004531474664451600256150ustar00rootroot00000000000000# Test that `cue login` fails when given an error # such as a device_code being expired. env CUE_CONFIG_DIR=$WORK/cueconfig oauthregistry device-code-expired ! exec cue login stdout 'open:.*user_code=user-code' stderr 'cannot obtain the OAuth2 token.*expired_token' ! exists cueconfig/logins.json cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/login_immediate.txtar000066400000000000000000000015011474664451600261060ustar00rootroot00000000000000# Test that `cue login` succeeds with the device flow # when the device login is immediately authorized and successful. env CUE_CONFIG_DIR=$WORK/cueconfig oauthregistry immediate-success exec cue login stdout 'open:.*user_code=user-code' # Ensure that only one token is stored. grep -count=1 '"registries": {' cueconfig/logins.json grep -count=1 '"access_token"' cueconfig/logins.json # Ensure the contents of the token look correct. grep -count=1 '"access_token": "secret-access-token"' cueconfig/logins.json grep -count=1 '"token_type": "Bearer"' cueconfig/logins.json # Timestamps are always stored in UTC and truncated to seconds. grep '"expiry": "20..-..-..T..:..:..Z"' cueconfig/logins.json # oauthregistry does not give a refresh token, and we use encoding/json's omitempty. ! grep '"refresh_token"' cueconfig/logins.json cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/login_pending.txtar000066400000000000000000000004441474664451600256010ustar00rootroot00000000000000# Test that `cue login` succeeds with the device flow # when the device login is authorized after the first polling request. env CUE_CONFIG_DIR=$WORK/cueconfig oauthregistry pending-success exec cue login stdout 'open:.*user_code=user-code' grep 'secret-access-token' cueconfig/logins.json cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/login_token.txtar000066400000000000000000000037731474664451600253050ustar00rootroot00000000000000env CUE_CONFIG_DIR=$WORK/cueconfig # When using the --token flag, we should not need to interact with a registry # to store the token into logins.json. oauthregistry device-code-expired # Unrecognized token formats fail for now. ! exec cue login --token=unrecognized_token_format_1234 stderr -count=1 'unknown token format, expected an appv1_ prefix' # An empty token is rejected, to prevent issues like --token=${UNSET_VAR}. ! exec cue login --token= stderr -count=1 'the --token flag needs a non-empty string' # Ensure that only one token is stored when starting from an empty logins.json file. exec cue login --token=appv1_validtoken1234 grep -count=1 '"registries": {' cueconfig/logins.json grep -count=1 '"access_token"' cueconfig/logins.json # Ensure the contents of the token look correct. grep -count=1 '"access_token": "appv1_validtoken1234"' cueconfig/logins.json # appv1 tokens do not include any other field. ! grep '"token_type"' cueconfig/logins.json ! grep '"expiry"' cueconfig/logins.json ! grep '"refresh_token"' cueconfig/logins.json # Ensure that we can store a token for a new registry on top of an existing logins.json file. exec cue login --token=appv1_validtoken5678 registry.mycorp.tld grep -count=1 '"registries": {' cueconfig/logins.json grep -count=1 '"registry\.mycorp\.tld"' cueconfig/logins.json grep -count=2 '"access_token"' cueconfig/logins.json # The full CUE_REGISTRY "simple" syntax is allowed. exec cue login --token=appv1_validtoken9999 fullsyntaxregistry.mycorp.tld/foobar+insecure grep -count=1 '"fullsyntaxregistry\.mycorp\.tld"' cueconfig/logins.json # When multiple registries are configured, none is selected by default. ! exec cue login --token=appv1_validtoken_neverused mycorp.tld=registry.mycorp.tld,registry.cue.works stderr 'need a single CUE registry to log into' env CUE_REGISTRY=mycorp.tld=registry.mycorp.tld,registry.cue.works ! exec cue login --token=appv1_validtoken_neverused stderr 'need a single CUE registry to log into' ! grep 'validtoken_neverused' cueconfig/logins.json cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/merge_interaction.txtar000066400000000000000000000006271474664451600264660ustar00rootroot00000000000000exec cue cmd dump cmp stdout expect-stdout -- combine.cue -- package kube map: [string]: spec: {} map: bartender: {} -- combine_tool.cue -- package kube import ( "encoding/yaml" "tool/cli" ) objects: [for x in map {x}] command: dump: { cli.Print & { text: yaml.MarshalStream(objects) } } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" -- expect-stdout -- spec: {} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/mod_registry.txtar000066400000000000000000000007721474664451600255000ustar00rootroot00000000000000skip 'TODO(mvdan): this test is racy; re-enable once we wait for the http server to be ready' # TODO: use a random unused port env CUE_REGISTRY=localhost:41331 exec cue mod registry ${CUE_REGISTRY} & exec cue mod publish v0.0.1 cmpenv stdout expect-stdout -- expect-stdout -- published mod.example/blah@v0.0.1 to ${CUE_REGISTRY}/mod.example/blah:v0.0.1 -- blah.cue -- package blah blah: 42 -- cue.mod/module.cue -- module: "mod.example/blah@v0" language: { version: "v0.9.0" } source: { kind: "self" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modedit_initial.txtar000066400000000000000000000051741474664451600261300ustar00rootroot00000000000000exec cue mod edit --source self cmp cue.mod/module.cue want-module-0 exec cue mod edit --source git cmp cue.mod/module.cue want-module-1 exec cue mod edit --drop-source cmp cue.mod/module.cue want-module-2 exec cue mod edit --require foo.bar@v0.2.3 cmp cue.mod/module.cue want-module-3 ! exec cue mod edit --require bad-module! cmp stderr want-stderr exec cue mod edit --drop-require foo.bar@v0 cmp cue.mod/module.cue want-module-4 exec cue mod edit --module othermain.org@v1 cmp cue.mod/module.cue want-module-5 # Set specific version. exec cue mod edit --language-version v0.9.2 cmp cue.mod/module.cue want-module-6 # Set latest version. exec cue mod edit --language-version current cmpenv cue.mod/module.cue want-module-7 # Set version earlier than earliest module schema version. ! exec cue mod edit --language-version v0.4.3 cmp stderr want-stderr-8 # Set version too new. ! exec cue mod edit --language-version v2.3.4 cmpenv stderr want-stderr-9 # Check that it's an error to set the version earlier than # allowed by some of the fields already present. exec cue mod edit --source self ! exec cue mod edit --language-version v0.8.0 cmp stderr want-stderr-10 -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.9.0-alpha.0" -- want-module-0 -- module: "main.org@v0" language: { version: "v0.9.0-alpha.0" } source: { kind: "self" } -- want-module-1 -- module: "main.org@v0" language: { version: "v0.9.0-alpha.0" } source: { kind: "git" } -- want-module-2 -- module: "main.org@v0" language: { version: "v0.9.0-alpha.0" } -- want-module-3 -- module: "main.org@v0" language: { version: "v0.9.0-alpha.0" } deps: { "foo.bar@v0": { v: "v0.2.3" } } -- want-stderr -- invalid argument "bad-module!" for "--require" flag: invalid module path@version "bad-module!" -- want-module-4 -- module: "main.org@v0" language: { version: "v0.9.0-alpha.0" } -- want-module-5 -- module: "othermain.org@v1" language: { version: "v0.9.0-alpha.0" } -- want-module-6 -- module: "othermain.org@v1" language: { version: "v0.9.2" } -- want-module-7 -- module: "othermain.org@v1" language: { version: "$CUE_LANGUAGE_VERSION" } -- want-stderr-8 -- invalid argument "v0.4.3" for "--language-version" flag: language version "v0.4.3" is too early for module.cue schema (earliest allowed is v0.8.0-alpha.0) -- want-stderr-9 -- invalid argument "v2.3.4" for "--language-version" flag: language version "v2.3.4" may not be after current language version $CUE_LANGUAGE_VERSION -- want-stderr-10 -- invalid resulting module.cue file after edits: cannot parse result: invalid module.cue file: source field is not allowed at this language version; need at least v0.9.0-alpha.0 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modedit_nomajorversion.txtar000066400000000000000000000006351474664451600275470ustar00rootroot00000000000000# Test that we can use cue mod edit to change # set a module path that does not contain a major # version suffix. exec cue mod init test.example cmp cue.mod/module.cue want-module exec cue mod edit --module other.example cmp cue.mod/module.cue want-module-2 -- want-module -- module: "test.example" language: { version: "v0.12.0" } -- want-module-2 -- module: "other.example" language: { version: "v0.12.0" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modedit_nonstrict.txtar000066400000000000000000000006631474664451600265200ustar00rootroot00000000000000# This test checks that cue mod edit works OK even when the # module file doesn't conform to the strict parsing. exec cue mod edit --source self cmp cue.mod/module.cue want-module -- cue.mod/module.cue -- module: "main.org" deps: "foo.com": v: "v1.2.3" language: version: "v0.9.0-alpha.0" -- want-module -- module: "main.org" language: { version: "v0.9.0-alpha.0" } source: { kind: "self" } deps: { "foo.com": { v: "v1.2.3" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modfix_initial.txtar000066400000000000000000000006621474664451600257660ustar00rootroot00000000000000# This test checks that the legacy module.cue fixing code # is wired up correctly. More comprehensive tests for # this functionality are inside the modfile package. exec cue mod fix cmp cue.mod/module.cue want-module exec cue mod fix cmp cue.mod/module.cue want-module -- cue.mod/module.cue -- module: "foo.com" foo: "bar" -- want-module -- module: "foo.com" language: { version: "v0.9.0" } custom: { legacy: { foo: "bar" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modget_bad_modulepath.txtar000066400000000000000000000005111474664451600272670ustar00rootroot00000000000000# Check that the error message when there's a bad module # path includes the path to the offending file (issue 3259) ! exec cue mod get example.com/foo cmp stderr want-stderr -- want-stderr -- cue.mod/module.cue: invalid module path: path "" has no major version -- cue.mod/module.cue -- module: "" language: version: "v0.9.2" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modget_initial.txtar000066400000000000000000000117461474664451600257640ustar00rootroot00000000000000# Check that cue mod get will upgrade an existing # dependency. cp cue.mod/module.cue module-original # cue mod get should update to v0.10.2 but not to the # latest prerelease v0.11.0-alpha exec cue mod get baz.org cmp cue.mod/module.cue want-module-1 exec cue export . cmp stdout want-stdout-1 # Check that the same thing happens when we use an # explicit @latest suffix. cp module-original cue.mod/module.cue exec cue mod get baz.org@latest cmp cue.mod/module.cue want-module-1 exec cue export . cmp stdout want-stdout-1 # We can update to the latest prerelease by providing an # explicit version. exec cue mod get baz.org@v0.11.0-alpha cmp cue.mod/module.cue want-module-2 exec cue export . cmp stdout want-stdout-2 # Check that we can also do the above by specifying # an explicit v0.11 prefix cp want-module-1 cue.mod/module.cue exec cue mod get baz.org@v0.11 cmp cue.mod/module.cue want-module-2 exec cue export . cmp stdout want-stdout-2 # If we try it again without an argument, it'll downgrade. exec cue mod get baz.org cmp cue.mod/module.cue want-module-1 exec cue export . cmp stdout want-stdout-1 # If we try to downgrade when some other dependency # is reliant on a later version, we'll get an error. ! exec cue mod get baz.org@v0.5.0 stderr 'other requirements prevent changing module baz.org@v0 to version v0.5.0 \(actual selected version: v0.10.1\)' -- want-module-1 -- module: "main.org@v0" language: { version: "v0.8.0" } deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.10.2" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- want-stdout-1 -- { "foo.com/bar/hello@v0": "v0.2.3", "bar.com@v0": "v0.5.0", "baz.org@v0": "v0.10.2", "main": "main", "example.com@v0": "v0.0.1" } -- want-module-2 -- module: "main.org@v0" language: { version: "v0.8.0" } deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.11.0-alpha" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- want-stdout-2 -- { "foo.com/bar/hello@v0": "v0.2.3", "bar.com@v0": "v0.5.0", "baz.org@v0": "v0.11.0-alpha", "main": "main", "example.com@v0": "v0.0.1" } -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.10.1" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- main.cue -- package main import "example.com@v0:main" main -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" deps: { "foo.com/bar/hello@v0": v: "v0.2.3" "bar.com@v0": v: "v0.5.0" } -- _registry/example.com_v0.0.1/top.cue -- package main import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry/example.com_v0.1.2/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.1.2/top.cue -- package main "example.com@v0": "v0.1.2" // TODO: import without a major version should // the major version from the module.cue file. main: "main" "example.com@v0": "v0.0.1" -- _registry/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" -- _registry/baz.org_v0.10.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.10.2/baz.cue -- package baz "baz.org@v0": "v0.10.2" -- _registry/baz.org_v0.11.0-alpha/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.11.0-alpha/baz.cue -- package baz "baz.org@v0": "v0.11.0-alpha" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modget_major_version.txtar000066400000000000000000000020541474664451600272000ustar00rootroot00000000000000# Check that cue mod get chooses the latest major version # when none is specified. exec cue mod get foo.org/bar cmp cue.mod/module.cue want-module exec cue export . cmp stdout want-stdout -- want-module -- module: "main.example" language: { version: "v0.8.0" } deps: { "foo.org/bar@v2": { v: "v2.0.0" } } -- want-stdout -- { "foo.org/bar@v2": "v2.0.0" } -- cue.mod/module.cue -- module: "main.example" language: version: "v0.8.0" -- main.cue -- package main import "foo.org/bar" bar -- _registry/foo.org_bar_v2.0.0/cue.mod/module.cue -- module: "foo.org/bar@v2" language: version: "v0.8.0" -- _registry/foo.org_bar_v2.0.0/bar.cue -- package bar "foo.org/bar@v2": "v2.0.0" -- _registry/foo.org_bar_v1.0.0/cue.mod/module.cue -- module: "foo.org/bar@v1" language: version: "v0.8.0" -- _registry/foo.org_bar_v1.0.0/bar.cue -- package bar "foo.org/bar@v1": "v1.0.0" -- _registry/foo.org_bar_v1.1.0/cue.mod/module.cue -- module: "foo.org/bar@v1" language: version: "v0.8.0" -- _registry/foo.org_bar_v1.1.0/bar.cue -- package bar "foo.org/bar@v1": "v1.1.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_badmodule.txtar000066400000000000000000000002001474664451600264320ustar00rootroot00000000000000! exec cue mod init bad cmp stderr want-stderr -- want-stderr -- malformed module path "bad": missing dot in first path element cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_badmoduleversion.txtar000066400000000000000000000002241474664451600300460ustar00rootroot00000000000000! exec cue mod init bad.com@v2.2 cmp stderr want-stderr -- want-stderr -- malformed module path "bad.com@v2.2": path can contain major version only cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_badpath.txtar000066400000000000000000000015461474664451600261170ustar00rootroot00000000000000# Check that the error messages for a bad module path are reasonably # self-explanatory. See https://cuelang.org/issue/3022 ! exec cue mod init github.com/FooBar cmp stderr want-stderr-1 ! exec cue mod init github.com/foo/.bar cmp stderr want-stderr-2 ! exec cue mod init github.com/foo/bar. cmp stderr want-stderr-3 ! exec cue mod init github.com/foo..bar cmp stderr want-stderr-4 -- want-stderr-1 -- malformed module path "github.com/FooBar": invalid char 'F' -- want-stderr-2 -- malformed module path "github.com/foo/.bar": leading '.' in path element -- want-stderr-3 -- malformed module path "github.com/foo/bar.": trailing '.' in path element -- want-stderr-4 -- malformed module path "github.com/foo..bar": path does not conform to OCI repository name restrictions; see https://github.com/opencontainers/distribution-spec/blob/HEAD/spec.md#pulling-manifests cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_majorversion.txtar000066400000000000000000000006141474664451600272250ustar00rootroot00000000000000env-fill want-module.cue env-fill want-module-experiment.cue rm cue.mod exec cue mod init foo.com/bar@v1 cmp cue.mod/module.cue want-module-experiment.cue exists cue.mod/usr exists cue.mod/pkg -- want-module.cue -- module: "foo.com/bar@v1" language: { version: "$CUE_LANGUAGE_VERSION" } -- want-module-experiment.cue -- module: "foo.com/bar@v1" language: { version: "$CUE_LANGUAGE_VERSION" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_noargs.txtar000066400000000000000000000003251474664451600257770ustar00rootroot00000000000000exec cue mod init env-fill want-module.cue cmp cue.mod/module.cue want-module.cue exists cue.mod/usr exists cue.mod/pkg -- want-module.cue -- module: "cue.example" language: { version: "$CUE_LANGUAGE_VERSION" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_nomajorversion.txtar000066400000000000000000000010151474664451600275560ustar00rootroot00000000000000env-fill want-module.cue env-fill want-module-experiment.cue # Although the major version will be implied as v0, # it's still omitted so that there's a possibility of compatibility # with earlier cue versions. exec cue mod init foo.com/bar cmp cue.mod/module.cue want-module-experiment.cue exists cue.mod/usr exists cue.mod/pkg -- want-module.cue -- module: "foo.com/bar" language: { version: "$CUE_LANGUAGE_VERSION" } -- want-module-experiment.cue -- module: "foo.com/bar" language: { version: "$CUE_LANGUAGE_VERSION" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_with_explicit_version.txtar000066400000000000000000000024131474664451600311270ustar00rootroot00000000000000# Check we can initialize the module with an explicit version. # Set current version. exec cue mod init --language-version current foo.example cmpenv cue.mod/module.cue want-module-1 rm cue.mod # Set specific version. exec cue mod init --language-version v0.9.2 foo.example cmp cue.mod/module.cue want-module-2 rm cue.mod # Set version earlier than earliest module schema version. ! exec cue mod init --language-version v0.4.3 foo.example cmp stderr want-stderr-3 rm cue.mod # Set version too new. ! exec cue mod init --language-version v2.3.4 foo.example cmp stderr want-stderr-4 rm cue.mod # Set version that's incompatible with the source field. ! exec cue mod init --language-version v0.8.0 --source self foo.example cmp stderr want-stderr-5 rm cue.mod -- want-module-1 -- module: "foo.example" language: { version: "$CUE_LANGUAGE_VERSION" } -- want-module-2 -- module: "foo.example" language: { version: "v0.9.2" } -- want-stderr-3 -- language version "v0.4.3" is too early for module.cue schema (earliest allowed is v0.8.0-alpha.0) -- want-stderr-4 -- language version "v2.3.4" may not be after current language version v0.12.0 -- want-stderr-5 -- cannot parse result: invalid module.cue file: source field is not allowed at this language version; need at least v0.9.0-alpha.0 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_without_version.txtar000066400000000000000000000007441474664451600277630ustar00rootroot00000000000000# Check that cue mod init is independent of the module version; # even though CUE's current module version will often be a v0 pseudo-version # or a pre-release, we will always use the current language version in init. exec cue mod init foo.example cmpenv cue.mod/module.cue want-module # cue mod tidy should be a no-op after cue mod init exec cue mod tidy cmpenv cue.mod/module.cue want-module -- want-module -- module: "foo.example" language: { version: "$CUE_LANGUAGE_VERSION" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modinit_withsource.txtar000066400000000000000000000014101474664451600266760ustar00rootroot00000000000000# Test that we can use the --source flag to cue mod init. env-fill $WORK/want-module.cue-0 env-fill $WORK/want-module.cue-1 mkdir $WORK/test0 cd $WORK/test0 exec cue mod init --source self test.example cmp cue.mod/module.cue $WORK/want-module.cue-0 mkdir $WORK/test1 cd $WORK/test1 exec cue mod init --source git test.example cmp cue.mod/module.cue $WORK/want-module.cue-1 mkdir $WORK/test2 cd $WORK/test2 ! exec cue mod init --source bad test.example cmp stderr $WORK/want-stderr -- want-module.cue-0 -- module: "test.example" language: { version: "$CUE_LANGUAGE_VERSION" } source: { kind: "self" } -- want-module.cue-1 -- module: "test.example" language: { version: "$CUE_LANGUAGE_VERSION" } source: { kind: "git" } -- want-stderr -- unrecognized source kind "bad" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modpublish_invalid_version.txtar000066400000000000000000000011201474664451600303760ustar00rootroot00000000000000memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY+insecure ! exec cue mod publish 1.2.3 cmp stderr want-stderr-1 ! exec cue mod publish v1.2 cmp stderr want-stderr-2 ! exec cue mod publish v1.2.3+build cmp stderr want-stderr-3 -- want-stderr-1 -- invalid publish version "1.2.3"; must be valid semantic version (see http://semver.org) -- want-stderr-2 -- publish version "v1.2" is not in canonical form -- want-stderr-3 -- publish version "v1.2.3+build" is not in canonical form -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.2" -- main.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modpublish_no_major_suffix.txtar000066400000000000000000000035301474664451600304020ustar00rootroot00000000000000# Test that cue mod publish succeeds when the module path lacks a major version suffix. # Using or developing the module locally works otherwise, even `cue mod tidy`. memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY+insecure exec cue export cmp stdout export.stdout exec cue mod tidy --check cp cue.mod/module.cue cue.mod/module.cue.original exec cue mod publish v0.0.1 # The inferred version is v0. Using any other major version will fail. ! exec cue mod publish v1.0.0 stderr 'publish version "v1.0.0" does not match implied major version "v0" in ".*module.cue"; must be v0.N.N' ! exec cue mod publish v2.0.0 stderr 'publish version "v2.0.0" does not match implied major version "v0" in ".*module.cue"; must be v0.N.N' # `cue mod fix` will not add add a major version suffix when missing. exec cue mod fix cmp cue.mod/module.cue cue.mod/module.cue.fixed cp cue.mod/module.cue.original cue.mod/module.cue exec cue mod edit --module main.example@v0 cmp cue.mod/module.cue cue.mod/module.cue.edited-with-v0 # Trying to publish with the wrong major version will fail. ! exec cue mod publish v1.0.0 stderr 'publish version "v1.0.0" does not match the major version "v0" declared in ".*module.cue"; must be v0.N.N' ! exec cue mod publish v2.0.0 stderr 'publish version "v2.0.0" does not match the major version "v0" declared in ".*module.cue"; must be v0.N.N' # Publishing with the right major version works. exec cue mod publish v0.0.2 -- export.stdout -- { "out": "hello world" } -- cue.mod/module.cue -- module: "main.example" language: version: "v0.9.0" source: kind: "self" -- cue.mod/module.cue.fixed -- module: "main.example" language: { version: "v0.9.0" } source: { kind: "self" } -- cue.mod/module.cue.edited-with-v0 -- module: "main.example@v0" language: { version: "v0.9.0" } source: { kind: "self" } -- main.cue -- package main out: "hello world" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modpublish_no_source.txtar000066400000000000000000000032631474664451600272110ustar00rootroot00000000000000# Test that cue mod publish fails when there is no # explicit source field in module.cue. # Also ensure that "tidy -check" does not complain if "publish" doesn't either. memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY+insecure # Starting with language.version=v0.9.0-alpha.2, we require source.kind to be set. cd ${WORK}/v0.9 exec cue mod tidy --check ! exec cue mod publish v1.0.0 cmp stderr publish.stderr # v0.8 language.version values can publish just like on CUE's v0.8.0 release. cd ${WORK}/v0.8 exec cue mod tidy --check exec cue mod publish v1.0.0 # Publishing with an ancient language.version, before we had a schema, fails. cd ${WORK}/v0.5 ! exec cue mod tidy --check cmp stderr both.stderr ! exec cue mod publish v1.0.0 cmp stderr both.stderr # Trying to publish without a language.version value is an error; # since CUE_EXPERIMENT=modules shipped in v0.8.0-alpha.1 we have inserted a version. # Moreover, the language version is a crucial bit of info for the registry. cd ${WORK}/none ! exec cue mod tidy --check cmp stderr both.stderr ! exec cue mod publish v1.0.0 cmp stderr both.stderr -- v0.9/publish.stderr -- no source field found in cue.mod/module.cue -- v0.9/cue.mod/module.cue -- module: "test.example/09@v1" language: version: "v0.9.0-alpha.2" -- v0.8/cue.mod/module.cue -- module: "test.example/08@v1" language: version: "v0.8.0-alpha.1" -- v0.5/both.stderr -- cannot find schema suitable for reading module file with language version "v0.5.0" -- v0.5/cue.mod/module.cue -- module: "test.example/05@v1" language: version: "v0.5.0" -- none/both.stderr -- no language version declared in module.cue; run 'cue mod fix' -- none/cue.mod/module.cue -- module: "test.example/none@v1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modpublish_no_vcs_directory.txtar000066400000000000000000000004471474664451600305710ustar00rootroot00000000000000# Test that cue mod publish fails when there is # a VCS source specified but no VCS directory # can be found. ! exec cue mod publish v1.0.0 stderr 'git VCS not found in any parent of ".+"' -- cue.mod/module.cue -- module: "x.example@v1" language: version: "v0.9.0-alpha.1" source: kind: "git" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modpublish_non_tidy.txtar000066400000000000000000000023321474664451600270340ustar00rootroot00000000000000# Test that cue mod publish fails when the module is not tidy # because one of the required dependencies is missing from module.cue. env OLD_CUE_REGISTRY=${CUE_REGISTRY} memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY+insecure ! exec cue mod publish v1.0.0 cmp stderr publish.stderr # Sanity check that we can tidy the module and then publish again. # Note that the dependency is in the original registry populated from _registry/. env CUE_REGISTRY=${OLD_CUE_REGISTRY} exec cue mod tidy env CUE_REGISTRY=$MEMREGISTRY+insecure cmp cue.mod/module.cue cue.mod/module.cue.tidy exec cue mod publish v1.0.1 -- publish.stderr -- module is not tidy, use 'cue mod tidy': missing dependency providing package example.com@v0:main -- cue.mod/module.cue -- module: "main.org@v1" language: version: "v0.9.0" source: kind: "self" -- cue.mod/module.cue.tidy -- module: "main.org@v1" language: { version: "v0.9.0" } source: { kind: "self" } deps: { "example.com@v0": { v: "v0.0.1" } } -- main.cue -- package main import "example.com@v0:main" main -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main "example.com@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modpublish_registry_not_enabled.txtar000066400000000000000000000002761474664451600314200ustar00rootroot00000000000000env CUE_EXPERIMENT=modules=false ! exec cue mod publish v1.0.0 cmp stderr want-stderr -- want-stderr -- cannot parse CUE_EXPERIMENT: cannot change default value of deprecated flag "modules" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modrename_changedrootqualifier.txtar000066400000000000000000000015511474664451600312130ustar00rootroot00000000000000# Make sure that things work OK when cue mod rename renames # a module where the last component differs. # Make a copy of the original files. cp cue.mod/module.cue cue.mod/module.cue-0 cp x.cue x.cue-0 cp y/y.cue y/y.cue-0 exec cue mod rename main.org/y cmp cue.mod/module.cue cue.mod/module.cue-1 cmp x.cue x.cue-1 cmp y/y.cue y/y.cue-1 # Check that renaming back to the original name # gets us back to the original content. exec cue mod rename main.org/x cmp cue.mod/module.cue cue.mod/module.cue-0 cmp x.cue x.cue-0 cmp y/y.cue y/y.cue-0 -- cue.mod/module.cue -- module: "main.org/x" language: { version: "v0.9.0" } -- x.cue -- package x x: 1 -- y/y.cue -- package y import "main.org/x" y: x.x -- cue.mod/module.cue-1 -- module: "main.org/y" language: { version: "v0.9.0" } -- x.cue-1 -- package x x: 1 -- y/y.cue-1 -- package y import "main.org/y:x" y: x.x cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modrename_diffmajorversion.txtar000066400000000000000000000023111474664451600303560ustar00rootroot00000000000000# Test that cue mod rename does not rewrite an import # of a package with a matching path but in a different major # version of the module. # First make sure everything is in canonical form. exec cue fmt ./... # Make a copy of the original files. cp cue.mod/module.cue cue.mod/module.cue-0 cp foo.cue foo.cue-0 cp bar/bar.cue bar/bar.cue-0 exec cue mod rename other.org/bar cmp cue.mod/module.cue cue.mod/module.cue-1 cmp foo.cue foo.cue-1 cmp bar/bar.cue bar/bar.cue-1 # Renaming back to the original name should # result in no changes from the original files. exec cue mod rename main.org/foo@v0 cmp cue.mod/module.cue cue.mod/module.cue-0 cmp foo.cue foo.cue-0 cmp bar/bar.cue bar/bar.cue-0 -- cue.mod/module.cue -- module: "main.org/foo@v0" language: { version: "v0.9.0" } deps: { "main.org/foo@v1": { v: "v1.2.3" } } -- foo.cue -- package foo import "main.org/foo@v1" x: foo.x -- bar/bar.cue -- package bar import "main.org/foo@v0" foo.x -- cue.mod/module.cue-1 -- module: "other.org/bar" language: { version: "v0.9.0" } deps: { "main.org/foo@v1": { v: "v1.2.3" } } -- foo.cue-1 -- package foo import "main.org/foo@v1" x: foo.x -- bar/bar.cue-1 -- package bar import "other.org/bar@v0:foo" foo.x cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modrename_initial.txtar000066400000000000000000000022331474664451600264430ustar00rootroot00000000000000# Test the basic functionality of cue mod rename. cp cue.mod/module.cue module.cue-0 exec cue mod rename main.org@v0 cmp cue.mod/module.cue module.cue-0 exec cue mod rename other.org@v0 cmp cue.mod/module.cue module.cue-1 cmp x.cue x.cue-1 cmp foo/foo.cue foo/foo.cue-1 exec cue mod rename another.blah/a cmp cue.mod/module.cue module.cue-2 cmp x.cue x.cue-2 cmp foo/foo.cue foo/foo.cue-2 -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.9.0-alpha.0" -- a.cue -- package a foo: "a" -- x.cue -- package x import ( "main.org/foo" "main.organization/blah" "something.else" ) foo.bar -- foo/foo.cue -- package foo import "main.org:a" a.foo -- module.cue-1 -- module: "other.org@v0" language: { version: "v0.9.0-alpha.0" } -- x.cue-1 -- package x import ( "other.org/foo" "main.organization/blah" "something.else" ) foo.bar -- foo/foo.cue-1 -- package foo import "other.org:a" a.foo -- module.cue-2 -- module: "another.blah/a" language: { version: "v0.9.0-alpha.0" } -- x.cue-2 -- package x import ( "another.blah/a/foo" "main.organization/blah" "something.else" ) foo.bar -- foo/foo.cue-2 -- package foo import "another.blah/a" a.foo cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_ambiguous_import.txtar000066400000000000000000000016231474664451600301030ustar00rootroot00000000000000# Test the errors resulting there's an "ambiguous import" error. # The errors _should_ report the full directory name for each module, # but currently only report the relative name. ! exec cue mod tidy cmp stderr want-stderr -- want-stderr -- failed to resolve "example.com/foo/bar@v0": ambiguous import: found package example.com/foo/bar@v0 in multiple modules: example.com@v0 v0.0.1 (foo/bar) example.com/foo@v0 v0.1.0 (bar) -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- main.cue -- package main import "example.com/foo/bar@v0" -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/foo/bar/x.cue -- package bar -- _registry/example.com_foo_v0.1.0/cue.mod/module.cue -- module: "example.com/foo@v0" language: version: "v0.8.0" -- _registry/example.com_foo_v0.1.0/bar/x.cue -- package bar cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_badpath.txtar000066400000000000000000000022331474664451600261170ustar00rootroot00000000000000# When the module resolution logic queries a registry for possible # module matches, it tries many possible prefixes. Some prefixes # might not be legitimate repository names even though they # are OK to use as package names. In such a case, a registry # might not return a 404 error, but some other kind of error. # The OCI proxy is one such registry. exec cue mod tidy cmp cue.mod/module.cue want-module exec cue export cmp stdout want-stdout -- want-module -- module: "cue.example@v0" language: { version: "v0.9.2" } deps: { "test.example/foo@v0": { v: "v0.0.1" default: true } } -- cue.mod/module.cue -- module: "cue.example@v0" language: version: "v0.9.2" -- want-stdout -- { "self": "test.example/foo/BarBaz" } -- main.cue -- package main // Note: test.example/foo/BarBaz is an illegal module path // (because it contains upper case) but is OK as a package path. import "test.example/foo/BarBaz" BarBaz -- _registry_proxy -- true -- _registry/test.example_foo_v0.0.1/cue.mod/module.cue -- module: "test.example/foo@v0" language: version: "v0.9.2" -- _registry/test.example_foo_v0.0.1/BarBaz/x.cue -- package BarBaz self: "test.example/foo/BarBaz" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_check.txtar000066400000000000000000000010521474664451600255670ustar00rootroot00000000000000# Check that cue mod tidy --check succeeds OK # even when the module file is formatted differently # e.g. language.version in a single line. exec cue mod tidy --check -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.100" // A comment. deps: "example.com@v0": v: "v0.0.1" -- main.cue -- package main import "example.com@v0:main" main -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main "example.com@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_check_fail.txtar000066400000000000000000000011041474664451600265600ustar00rootroot00000000000000# Check that cue mod tidy --check fails when some dependencies aren't present. ! exec cue mod tidy --check cmp stderr want-stderr -- want-stderr -- module is not tidy, use 'cue mod tidy': missing dependency providing package example.com@v0:main -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- main.cue -- package main import "example.com@v0:main" main -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main "example.com@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_excluded_files_error.txtar000066400000000000000000000007731474664451600307130ustar00rootroot00000000000000! exec cue mod tidy cmp stderr expect-stderr -- expect-stderr -- failed to resolve "test.example/d1": no files in package directory with package name "d1" (1 files were excluded) -- cue.mod/module.cue -- module: "test.example/main" language: version: "v0.9.2" -- main.cue -- package main import "test.example/d1" x: d1 -- _registry/test.example_d1_v0.0.1/cue.mod/module.cue -- module: "test.example/d1" language: version: "v0.9.2" -- _registry/test.example_d1_v0.0.1/x.cue -- @if(notused) package d1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_initial.txtar000066400000000000000000000111521474664451600261450ustar00rootroot00000000000000# Check that cue mod tidy can add dependencies by # querying the registry, that it doesn't upgrade existing # dependencies, and that it removes dependencies that # aren't needed any more. exec cue mod tidy cmp cue.mod/module.cue want-module # Check that the resulting module evaluates as expected. exec cue export . cmp stdout want-stdout # Check that the tidy check succeeds exec cue mod tidy --check # Check what the structure of CUE_CACHE_DIR looks like after fetching modules. find-files ${CUE_CACHE_DIR} cmp stdout cue-cache-dir.files # Unused dependencies should not have their entire source downloaded or extracted. ! stdout 'unused\.com.*\.zip$' -- want-module -- module: "main.org" language: { version: "v0.8.0" } deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.10.1" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- want-stdout -- { "foo.com/bar/hello@v0": "v0.2.3", "bar.com@v0": "v0.5.0", "baz.org@v0": "v0.10.1", "main": "main", "example.com@v0": "v0.0.1" } -- cue.mod/module.cue -- module: "main.org" language: version: "v0.8.0" deps: "example.com": v: "v0.0.1" deps: "unused.com@v0": v: "v0.2.4" -- main.cue -- package main import "example.com@v0:main" main -- cue-cache-dir.files -- .tmp/cache/mod/download/bar.com/@v/v0.5.0.lock .tmp/cache/mod/download/bar.com/@v/v0.5.0.mod .tmp/cache/mod/download/bar.com/@v/v0.5.0.zip .tmp/cache/mod/download/baz.org/@v/v0.10.1.lock .tmp/cache/mod/download/baz.org/@v/v0.10.1.mod .tmp/cache/mod/download/baz.org/@v/v0.10.1.zip .tmp/cache/mod/download/example.com/@v/v0.0.1.lock .tmp/cache/mod/download/example.com/@v/v0.0.1.mod .tmp/cache/mod/download/example.com/@v/v0.0.1.zip .tmp/cache/mod/download/foo.com/bar/hello/@v/v0.2.3.lock .tmp/cache/mod/download/foo.com/bar/hello/@v/v0.2.3.mod .tmp/cache/mod/download/foo.com/bar/hello/@v/v0.2.3.zip .tmp/cache/mod/download/unused.com/@v/v0.2.4.lock .tmp/cache/mod/download/unused.com/@v/v0.2.4.mod .tmp/cache/mod/extract/bar.com@v0.5.0/bar/x.cue .tmp/cache/mod/extract/bar.com@v0.5.0/cue.mod/module.cue .tmp/cache/mod/extract/baz.org@v0.10.1/baz.cue .tmp/cache/mod/extract/baz.org@v0.10.1/cue.mod/module.cue .tmp/cache/mod/extract/example.com@v0.0.1/cue.mod/module.cue .tmp/cache/mod/extract/example.com@v0.0.1/top.cue .tmp/cache/mod/extract/foo.com/bar/hello@v0.2.3/cue.mod/module.cue .tmp/cache/mod/extract/foo.com/bar/hello@v0.2.3/x.cue -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" deps: { "foo.com/bar/hello@v0": v: "v0.2.3" "bar.com@v0": v: "v0.5.0" } -- _registry/example.com_v0.0.1/top.cue -- package main import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry/unused.com_v0.2.4/cue.mod/module.cue -- module: "unused.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.1.2/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.1.2/top.cue -- package main "example.com@v0": "v0.1.2" // TODO: import without a major version should // the major version from the module.cue file. main: "main" "example.com@v0": "v0.0.1" -- _registry/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_logging.txtar000066400000000000000000000017261474664451600261500ustar00rootroot00000000000000# Check that we see HTTP log messages printed when enabled. env CUE_DEBUG=http # Smoke test that the logging looks reasonable. The actual log messages # are tested more fully in the httplog package itself. exec cue mod tidy stderr '{"time":".*","level":"INFO","msg":"http client->","info":{"id":[0-9]+,"method":"GET","url":"http://[^/]+/v2/example.com/tags/list\?n=\d+","contentLength":0,"header":{"User-Agent":\["Cue/[^ ]+ \(cmd/cue; .*\) Go/[^ ]+ \(.*\)"\]}}}' # Check that the resulting module evaluates as expected. exec cue export . cmp stdout want-stdout -- want-stdout -- { "example.com@v0": "v0.0.1", "main": "main" } -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- main.cue -- package main import "example.com@v0:main" main "main": "main" -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main "example.com@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_missing_major_version.txtar000066400000000000000000000005651474664451600311300ustar00rootroot00000000000000# Check that cue mod tidy does not add a major # version suffix to the module field unless it is # already present. exec cue mod tidy --check exec cue mod tidy cmp cue.mod/module.cue want-cue.mod -- want-cue.mod -- module: "main.org" language: { version: "v0.8.100" } -- cue.mod/module.cue -- module: "main.org" language: version: "v0.8.100" -- main.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_nofallback.txtar000066400000000000000000000010241474664451600266050ustar00rootroot00000000000000# Check that we can tidy a module when using a no-fallback # "none" registry. env CUE_REGISTRY=foo.com/bar=$CUE_REGISTRY1,none exec cue mod tidy exec cue eval . cmp stdout want-stdout -- want-stdout -- x: "hello" -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- main.cue -- package main import "foo.com/bar/baz@v0" baz -- _registry1/foo.com_bar_v0.0.1/cue.mod/module.cue -- module: "foo.com/bar@v0" language: version: "v0.8.0" -- _registry1/foo.com_bar_v0.0.1/baz/baz.cue -- package baz x: "hello" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_non_root.txtar000066400000000000000000000007711474664451600263560ustar00rootroot00000000000000# Check that cue mod tidy works OK even when not # run in the module's root directory. cd x/y exec cue mod tidy cd $WORK cmp cue.mod/module.cue want-module -- want-module -- module: "main.org@v0" language: { version: "v0.8.0" } -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- x/y/z.cue -- package y -- _registry/example.com_v0.0.1/cue.mod/module.cue -- // This file is just here to ensure that CUE_REGISTRY etc is set. module: "example.com@v0" language: version: "v0.8.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_not_found.txtar000066400000000000000000000006431474664451600265120ustar00rootroot00000000000000! exec cue mod get other.test@v0 cmp stderr want-stderr -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.10.0" -- want-stderr -- no versions found for module other.test@v0 -- main.cue -- package main import "other.test/foo" x: foo -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_registry_not_enabled.txtar000066400000000000000000000002611474664451600307150ustar00rootroot00000000000000env CUE_EXPERIMENT=modules=0 ! exec cue mod tidy cmp stderr want-stderr -- want-stderr -- cannot parse CUE_EXPERIMENT: cannot change default value of deprecated flag "modules" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_with_build_attrs.txtar000066400000000000000000000071541474664451600300720ustar00rootroot00000000000000# Check that, for the purposes of `cue mod tidy`, build attributes are always considered # to be enabled in the main module but disabled in dependencies. # Also check that _tool.cue and _test.cue files are ignored when they # are part of external dependencies. exec cue mod tidy cmp cue.mod/module.cue want-module # Note that test.example.d3 should _not_ appear # in the dependencies because it's guarded by a build # tag that should be considered to be false. ! grep test.example/d3 want-module # On the other hand, d4 _should_ appear in the # dependencies, because it's guarded by the negation # of a build tag. grep test.example/d4 want-module exec cue eval cmp stdout want-stdout-1 exec cue eval -t prod cmp stdout want-stdout-2 ! exec cue eval -t notknown stderr 'tag "notknown" not used in any file' -- want-module -- module: "main.org" language: { version: "v0.9.2" } deps: { "test.example/d1@v0": { v: "v0.0.1" default: true } "test.example/d2@v0": { v: "v0.0.1" default: true } "test.example/d4@v0": { v: "v0.0.1" default: true } } -- want-stdout-1 -- prod: false x: { self: "test.example/d2" } -- want-stdout-2 -- prod: true x: { self: "test.example/d1" prodenabled: false y: { self: "test.example/d4" } } -- cue.mod/module.cue -- module: "main.org" language: { version: "v0.9.2" } -- foo_prod.cue -- @if(prod) package foo import "test.example/d1" prod: true x: d1 -- foo_nonprod.cue -- @if(!prod) package foo import "test.example/d2" prod: false x: d2 -- ignorable.cue -- @ignore() package foo import "test.example/d7" ignore: d7 -- _registry/test.example_d1_v0.0.1/cue.mod/module.cue -- module: "test.example/d1" language: version: "v0.9.2" -- _registry/test.example_d1_v0.0.1/x.cue -- @if(prod) package d1 import "test.example/d3" self: "test.example/d1" prodenabled: true y: d3 -- _registry/test.example_d1_v0.0.1/y.cue -- @if(!prod) package d1 import "test.example/d4" self: "test.example/d1" prodenabled: false y: d4 -- _registry/test.example_d1_v0.0.1/a_tool.cue -- package d1 import "test.example/d5" y: d5 -- _registry/test.example_d1_v0.0.1/a_test.cue -- package d1 import "test.example/d6" y: d6 -- _registry/test.example_d1_v0.0.1/ignorable.cue -- @ignore() package d1 import "test.example/d8" ignore: d8 -- _registry/test.example_d2_v0.0.1/cue.mod/module.cue -- module: "test.example/d2" language: version: "v0.9.2" -- _registry/test.example_d2_v0.0.1/x.cue -- package d2 self: "test.example/d2" -- _registry/test.example_d3_v0.0.1/cue.mod/module.cue -- module: "test.example/d3" language: version: "v0.9.2" -- _registry/test.example_d3_v0.0.1/x.cue -- package d3 self: "test.example/d3" -- _registry/test.example_d4_v0.0.1/cue.mod/module.cue -- module: "test.example/d4" language: version: "v0.9.2" -- _registry/test.example_d4_v0.0.1/x.cue -- package d4 self: "test.example/d4" -- _registry/test.example_d5_v0.0.1/cue.mod/module.cue -- module: "test.example/d5" language: version: "v0.9.2" -- _registry/test.example_d5_v0.0.1/x.cue -- package d5 self: "test.example/d5" -- _registry/test.example_d6_v0.0.1/cue.mod/module.cue -- module: "test.example/d6" language: version: "v0.9.2" -- _registry/test.example_d6_v0.0.1/x.cue -- package d6 self: "test.example/d6" -- _registry/test.example_d7_v0.0.1/cue.mod/module.cue -- module: "test.example/d7" language: version: "v0.9.2" -- _registry/test.example_d7_v0.0.1/x.cue -- package d7 self: "test.example/d7" -- _registry/test.example_d8_v0.0.1/cue.mod/module.cue -- module: "test.example/d8" language: version: "v0.9.2" -- _registry/test.example_d8_v0.0.1/x.cue -- package d8 self: "test.example/d8" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_with_existing_version.txtar000066400000000000000000000012261474664451600311470ustar00rootroot00000000000000# Check that cue mod tidy won't change the language # version when the field is already present in the module.cue file. exec cue mod tidy cmp cue.mod/module.cue want-module # Check that the resulting module evaluates as expected. exec cue export . cmp stdout want-stdout -- want-stdout -- { "x": 1 } -- want-module -- module: "main.org@v0" language: { version: "v0.8.100" } -- cue.mod/module.cue -- module: "main.org@v0" language: { version: "v0.8.100" } -- main.cue -- package main x: 1 -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_with_generated_code.txtar000066400000000000000000000016571474664451600305100ustar00rootroot00000000000000# Check that cue mod tidy can add dependencies by # querying the registry, that it doesn't upgrade existing # dependencies, and that it removes dependencies that # aren't needed any more. exec cue mod tidy cmp cue.mod/module.cue want-module # Check that the resulting module evaluates as expected. exec cue export . cmp stdout want-stdout -- want-module -- module: "main.org@v0" language: { version: "v0.8.0" } deps: { "example.com@v0": { v: "v0.0.1" } } -- want-stdout -- { "example.com": "v0.0.1", "bar": "local" } -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" -- cue.mod/gen/foo.com/bar/x.cue -- package bar bar: "local" -- main.cue -- package main import ( "example.com@v0:main" "foo.com/bar" ) main bar -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main "example.com": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/modtidy_with_version.txtar000066400000000000000000000007151474664451600272370ustar00rootroot00000000000000# Check that cue mod tidy fails when there is no version # present in the module.cue file. ! exec cue mod tidy cmp stderr want-stderr -- want-stderr -- no language version declared in module.cue; run 'cue mod fix' -- cue.mod/module.cue -- module: "main.org@v0" -- main.cue -- package main x: 1 -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/module_compatibility_backwards.txtar000066400000000000000000000115151474664451600312250ustar00rootroot00000000000000# This test checks for backwards compatibility with modules developed # using older versions of CUE. It checks that: # # 1) Downstream consumption does work, where one only needs to load CUE packages. # `cue export`, loading as a dependency via `cue/load`, etc. # 2) Upstream development does work, where one may need to modify cue.mod/module.cue # or publish the module to a registry. `cue mod tidy`, `cue mod publish`, etc. # # TODO(mvdan): once we split up language.version from the schema version, # cover scenarios where just one of them is older. # This test uses an in-memory registry for `cue mod publish` to be able to succeed, # but some tests will also need ORIG_CUE_REGISTRY to fetch modules from _registry/ below. memregistry MEMREGISTRY env ORIG_CUE_REGISTRY=${CUE_REGISTRY} env CUE_REGISTRY=$MEMREGISTRY+insecure # A module that was created before the modules experiment, # without a major version suffix nor a language version. cd ${WORK}/premodules # Downstream consumption via cue.mod/*/ works. # Downstream consumption via a registry is not possible as its module path lacks a major version suffix. exec cue export stdout '"downstream": "hello from premodules.example"' # Continue inside the module's own directory as if we had cloned it directly. cd ${WORK} mv premodules/cue.mod/pkg/premodules.example premodules-downstream-direct cd premodules-downstream-direct # Downstream consumption via `cue export` fails; when the current module lacks # a language.version field, we always nudge the user or developer to add one. ! exec cue export stderr '^no language version declared in module.cue; run ''cue mod fix''$' # Upstream development works once `cue mod fix` adds a language.version field. ! exec cue mod tidy --check stderr '^no language version declared in module.cue; run ''cue mod fix''$' ! exec cue mod get some.dependency stderr '^no language version declared in module.cue; run ''cue mod fix''$' ! exec cue mod publish v0.0.2 stderr '^no language version declared in module.cue; run ''cue mod fix''$' exec cue mod fix cmp cue.mod/module.cue ${WORK}/premodules-module.cue.fixed exec cue export stdout '"hello from premodules.example"' exec cue mod tidy --check # Upstream publishing then works once a source.kind is chosen by the user. ! exec cue mod publish v0.0.2 stderr '^no source field found in cue.mod/module.cue$' exec cue mod edit --source self exec cue mod publish v0.0.2 # A module that was created with a language.version of v0.8.0. cd ${WORK}/v0.8.0-downstream-deps # Downstream consumption via a registry works. # Note that we need to point CUE_REGISTRY back to the contents inside _registry/ below. env CUE_REGISTRY=${ORIG_CUE_REGISTRY} exec cue export stdout '"downstream": "hello from v0.8.0.example"' env CUE_REGISTRY=$MEMREGISTRY+insecure # Downstream consumption via cue.mod/*/ works. cd ${WORK}/v0.8.0-downstream-cuemod mv ${WORK}/_registry/v0.8.0.example_v0.0.1 cue.mod/pkg/v0.8.0.example exec cue export stdout '"downstream": "hello from v0.8.0.example"' # Continue inside the module's own directory as if we had cloned it directly. cd ${WORK} mv v0.8.0-downstream-cuemod/cue.mod/pkg/v0.8.0.example v0.8.0-downstream-direct cd v0.8.0-downstream-direct # Downstream consumption via `cue export` works. exec cue export stdout '"hello from v0.8.0.example"' # Upstream development via `cue mod tidy` works. exec cue mod tidy --check # Upstream publishing works directly, as v0.8.0 has no source.kind. exec cue mod publish v0.0.2 -- premodules/cue.mod/module.cue -- module: "downstream.example" language: version: "v0.9.0" -- premodules/downstream.cue -- package downstream import "premodules.example:root" downstream: root -- premodules/cue.mod/pkg/premodules.example/cue.mod/module.cue -- module: "premodules.example" -- premodules-module.cue.fixed -- module: "premodules.example" language: { version: "v0.9.0" } -- premodules/cue.mod/pkg/premodules.example/root.cue -- package root import "premodules.example/subpkg" subpkg -- premodules/cue.mod/pkg/premodules.example/subpkg/subpkg.cue -- package subpkg "hello from premodules.example" -- v0.8.0-downstream-deps/cue.mod/module.cue -- module: "downstream.example" language: version: "v0.9.0" deps: "v0.8.0.example": v: "v0.0.1" -- v0.8.0-downstream-deps/downstream.cue -- package downstream import "v0.8.0.example:root" downstream: root -- v0.8.0-downstream-cuemod/cue.mod/module.cue -- module: "downstream.example" language: version: "v0.9.0" -- v0.8.0-downstream-cuemod/cue.mod/pkg/.mkdir -- -- v0.8.0-downstream-cuemod/downstream.cue -- package downstream import "v0.8.0.example:root" downstream: root -- _registry/v0.8.0.example_v0.0.1/cue.mod/module.cue -- module: "v0.8.0.example@v0" language: version: "v0.8.0" -- _registry/v0.8.0.example_v0.0.1/root.cue -- package root import "v0.8.0.example/subpkg" subpkg -- _registry/v0.8.0.example_v0.0.1/subpkg/subpkg.cue -- package subpkg "hello from v0.8.0.example" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/module_compatibility_forwards.txtar000066400000000000000000000107771474664451600311240ustar00rootroot00000000000000# This test checks for forwards compatibility with modules developed # using newer versions of CUE. It checks that: # # 1) Downstream consumption does not work, as we don't support the newer language spec version. # 2) Upstream development does not work, as modifying cue.mod/module.cue or publishing # the module is not safe when we don't have or understand the schema it uses. # # TODO(mvdan): once we split up language.version from the schema version, # cover scenarios where just one of them is too new, # as we should allow downstream consumption when only the module schema version is too new. # A module that was created with a language.version of ${CUE_LANGUAGE_VERSION_BUGFIX}, # which is like the current ${CUE_LANGUAGE_VERSION} but with a higher bugfix release. # For example, if ${CUE_LANGUAGE_VERSION} is v0.10.0 or v0.10.5, ${CUE_LANGUAGE_VERSION_BUGFIX} is v0.10.99. # Even though the language spec should not change in bugfix releases, # we still treat the language version as a hard minimum following semver. cd ${WORK}/bugfix-newer env-fill cue.mod/pkg/bugfix-newer.example/cue.mod/module.cue # TODO(mvdan): downstream consumption via cue.mod/*/ works when it should not, # because we do not yet use language.version as a minimum for parsing or evaluating CUE. exec cue export stdout '"downstream": "hello from bugfix-newer.example"' # TODO(mvdan): test downstream consumption via a registry; note that _registry/ complains # because it is unable to parse the module.cue file with a schema that is too new. # Continue inside the module's own directory as if we had cloned it directly. cd ${WORK} mv bugfix-newer/cue.mod/pkg/bugfix-newer.example bugfix-newer-downstream-direct cd bugfix-newer-downstream-direct # Downstream consumption via `cue export` does not work as we don't support the language spec version. ! exec cue export cmp stderr ${WORK}/bugfix-newer-toonew.stderr # Upstream development and publishing is forbidden as we don't have or understand the schema. ! exec cue mod tidy --check cmp stderr ${WORK}/bugfix-newer-toonew.stderr ! exec cue mod publish v0.0.2 cmp stderr ${WORK}/bugfix-newer-toonew.stderr # A module that was created with a language.version of v0.99.0 in the far future. cd ${WORK}/v0.99.0 # TODO(mvdan): downstream consumption via cue.mod/*/ works when it should not, # because we do not yet use language.version as a minimum for parsing or evaluating CUE. exec cue export stdout '"downstream": "hello from v0.99.0.example"' # TODO(mvdan): test downstream consumption via a registry; note that _registry/ complains # because it is unable to parse the module.cue file with a schema that is too new. # Continue inside the module's own directory as if we had cloned it directly. cd ${WORK} mv v0.99.0/cue.mod/pkg/v0.99.0.example v0.99.0-downstream-direct cd v0.99.0-downstream-direct # Downstream consumption via `cue export` does not work as we don't support the language spec version. ! exec cue export cmp stderr ${WORK}/v0.99.0-toonew.stderr # Upstream development and publishing is forbidden as we don't have or understand the schema. ! exec cue mod tidy --check cmp stderr ${WORK}/v0.99.0-toonew.stderr ! exec cue mod publish v0.0.2 cmp stderr ${WORK}/v0.99.0-toonew.stderr -- bugfix-newer-toonew.stderr -- language version "v0.12.99" declared in module.cue is too new for current language version "v0.12.0" -- bugfix-newer/cue.mod/module.cue -- module: "downstream.example" language: version: "v0.9.0" -- bugfix-newer/downstream.cue -- package downstream import "bugfix-newer.example:root" downstream: root -- bugfix-newer/cue.mod/pkg/bugfix-newer.example/cue.mod/module.cue -- module: "bugfix-newer.example" language: version: "${CUE_LANGUAGE_VERSION_BUGFIX}" -- bugfix-newer/cue.mod/pkg/bugfix-newer.example/root.cue -- package root import "bugfix-newer.example/subpkg" subpkg -- bugfix-newer/cue.mod/pkg/bugfix-newer.example/subpkg/subpkg.cue -- package subpkg "hello from bugfix-newer.example" -- v0.99.0-toonew.stderr -- language version "v0.99.0" declared in module.cue is too new for current language version "v0.12.0" -- v0.99.0/cue.mod/module.cue -- module: "downstream.example" language: version: "v0.9.0" -- v0.99.0/downstream.cue -- package downstream import "v0.99.0.example:root" downstream: root -- v0.99.0/cue.mod/pkg/v0.99.0.example/cue.mod/module.cue -- module: "v0.99.0.example" language: version: "v0.99.0" -- v0.99.0/cue.mod/pkg/v0.99.0.example/root.cue -- package root import "v0.99.0.example/subpkg" subpkg -- v0.99.0/cue.mod/pkg/v0.99.0.example/subpkg/subpkg.cue -- package subpkg "hello from v0.99.0.example" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/module_path_dash.txtar000066400000000000000000000054611474664451600262710ustar00rootroot00000000000000# Test that it's possible to publish, depend on, and import a module # whose path ends with a name containing a dash like foo-bar. # Note that foo-bar is not a valid package name, but is allowed in a module path. # Note that this is similar to pkg_resolution_path_element_invalid_ident.txtar, # but this concerns module paths and publishing/retrieving them. memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY cd publisher exec cue mod publish v1.0.0 cd .. # First, see what happens if the user forgot to qualify the CUE package import. # mod tidy should work, because it is able to locate a module containing a package # at the given import path, but export should fail, as no explicit package is named. cd importer-noqualifier exec cue mod tidy cmp cue.mod/module.cue cue.mod/module.cue.want ! exec cue export . cmp stderr export.stderr cd .. # Similarly, "getting" the entire module should work, even if no valid package name # can be derived from the module path. cd getter-noqualifier exec cue mod get main.org/foo-bar cmp cue.mod/module.cue cue.mod/module.cue.want cd .. # With an explicit qualifier, both mod tidy and export work just fine. cd importer-withqualifier exec cue mod tidy cmp cue.mod/module.cue cue.mod/module.cue.want exec cue export . cmp stdout export.stdout cd .. -- importer-noqualifier/cue.mod/module.cue -- module: "main.org/importer-noqualifier@v1" language: { version: "v0.9.0" } -- importer-noqualifier/cue.mod/module.cue.want -- module: "main.org/importer-noqualifier@v1" language: { version: "v0.9.0" } deps: { "main.org/foo-bar@v1": { v: "v1.0.0" } } -- importer-noqualifier/main.cue -- package importer import "main.org/foo-bar@v1" foobar.contents -- importer-noqualifier/export.stderr -- main.org/importer-noqualifier@v1: import failed: cannot determine package name for "main.org/foo-bar@v1"; set it explicitly with ':': ./main.cue:3:8 -- getter-noqualifier/cue.mod/module.cue -- module: "main.org/getter-noqualifier@v1" language: { version: "v0.9.0" } -- getter-noqualifier/cue.mod/module.cue.want -- module: "main.org/getter-noqualifier@v1" language: { version: "v0.9.0" } deps: { "main.org/foo-bar@v1": { v: "v1.0.0" } } -- importer-withqualifier/cue.mod/module.cue -- module: "main.org/importer-withqualifier@v1" language: { version: "v0.9.0" } -- importer-withqualifier/cue.mod/module.cue.want -- module: "main.org/importer-withqualifier@v1" language: { version: "v0.9.0" } deps: { "main.org/foo-bar@v1": { v: "v1.0.0" } } -- importer-withqualifier/main.cue -- package importer import "main.org/foo-bar@v1:foobar" foobar.contents -- importer-withqualifier/export.stdout -- "source for foo-bar" -- publisher/cue.mod/module.cue -- module: "main.org/foo-bar@v1" language: { version: "v0.9.0" } source: { kind: "self" } -- publisher/main.cue -- package foobar contents: "source for foo-bar" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/no_read_stdin.txtar000066400000000000000000000003211474664451600255670ustar00rootroot00000000000000# try to trick cue reading from a perpetually open stdin by placing a file # named '-' in the current directory. ! exec cue eval stdin - cmp stderr expect-stderr -- - -- -- expect-stderr -- no CUE files in . cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/pkg_patterns.txtar000066400000000000000000000061021474664451600254630ustar00rootroot00000000000000# Test the various kinds of wildcard patterns that we do not support. # Patterns on modules other than the current module are not supported, # even though one valid package could be matched. ! exec cue eval example.com/foo/... cmp stderr external.stderr exec cue eval example.com/foo stdout -count=1 '^self: "example.com/foo"$' # The "all", "cmd", and "std" patterns were inherited from Go, # but they do nothing useful right now. # TODO: decide whether to support or reject these. ! exec cue eval all cmp stderr all.stderr ! exec cue eval cmd cmp stderr cmd.stderr ! exec cue eval std cmp stderr std.stderr # A lone wildcard, perhaps equivalent to "all", is not supported for now. # TODO: much like "all", decide whether to support or reject this. ! exec cue eval ... cmp stderr dots.stderr # Patterns with a leading wildcard are not supported either, # as they could match any module ever published, # even though one valid package could be matched. ! exec cue eval .../leaf cmp stderr dots-prefix.stderr exec cue eval ./alpha1/leaf stdout -count=1 '^self: "mod.com/alpha1/leaf"$' # A wildcard in the middle of a pattern, with the current module as a prefix # either as "dot" or as the full path. # TODO: Why does this succeed? What does the output mean? This seems broken. exec cue eval ./.../leaf stdout -count=1 '^"example.com/foo"$' # TODO: Unlike other cases, this still returns a "matched no packages" error. ! exec cue eval mod.com/.../leaf cmp stderr current-dots-middle.stderr # A wildcard in the middle of a pattern, with a dependency module as a prefix. ! exec cue eval example.com/foo/.../bar cmp stderr external-dots-middle.stderr # Matching many external modules, which could mean registry requests. ! exec cue eval example.com/... cmp stderr external-dots-multimod.stderr -- external.stderr -- pattern not allowed in external package path "example.com/foo/..." -- all.stderr -- cue: "all" matched no packages -- cmd.stderr -- cue: "cmd" matched no packages -- std.stderr -- cue: "std" matched no packages -- dots.stderr -- pattern not allowed in external package path "..." -- dots-prefix.stderr -- pattern not allowed in external package path ".../leaf" -- current-dots-middle.stderr -- cue: "mod.com/.../leaf" matched no packages -- external-dots-middle.stderr -- pattern not allowed in external package path "example.com/foo/.../bar" -- external-dots-multimod.stderr -- pattern not allowed in external package path "example.com/..." -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" deps: "example.com/foo": v: "v0.0.1" -- root.cue -- package root import "example.com/foo" foo.self -- alpha1/leaf/leaf.cue -- package leaf self: "mod.com/alpha1/leaf" -- beta1/leaf/leaf.cue -- package leaf self: "mod.com/beta1/leaf" -- beta1/beta2/leaf/leaf.cue -- package leaf self: "mod.com/beta1/beta2/leaf" -- _registry/example.com_foo_v0.0.1/cue.mod/module.cue -- module: "example.com/foo@v0" language: version: "v0.8.0" -- _registry/example.com_foo_v0.0.1/foo.cue -- package foo self: "example.com/foo" -- _registry/example.com_foo_v0.0.1/bar/bar.cue -- package bar self: "example.com/foo/bar" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/pkg_resolution_focus.txtar000066400000000000000000000016361474664451600272340ustar00rootroot00000000000000# Test that only packages explicitly implied from command line # arguments and their dependencies are scanned. # See https://cuelang.org/issue/3155 for context. exec cue eval ./a cmp stdout stdout.golden -- stdout.golden -- b: 5 foo: true -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" deps: "example.com/foo": v: "v0.0.1" -- root.cue -- package root import "mod.com/x" x -- a/a.cue -- package a import "mod.com/b" b -- b/b.cue -- package b import "example.com/foo" b: 5 foo -- c/invalid.cue -- // This file should be ignored because it's not part of the dependencies // mentioned on the command line. // We use invalid syntax to surface an error if the file is not ignored as expected. package c import 435 -- _registry/example.com_foo_v0.0.1/cue.mod/module.cue -- module: "example.com/foo@v0" language: version: "v0.8.0" -- _registry/example.com_foo_v0.0.1/foo.cue -- package foo foo: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/pkg_resolution_multiple_packages_build_attr.txtar000066400000000000000000000007541474664451600340170ustar00rootroot00000000000000# Test that a wildcard pattern respects build attributes when determining # what packages it resolves to. exec cue eval ./... cmp stdout stdout.golden ! exec cue eval -t something ./... stderr '^found packages "x" \(x.cue\) and "y" \(y.cue\) in ".*x"$' -- stdout.golden -- x: 5 // --- x: 5 -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- root.cue -- package root import "mod.com/x" x -- x/x.cue -- package x x: 5 -- x/y.cue -- @if(something) package y y: 5 pkg_resolution_multiple_packages_no_matching_path_element.txtar000066400000000000000000000016331474664451600366170ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script# Test that a relative package path functions the same as an absolute package path # when there are no packages in the directory with names that match # the final element of the import path. ! exec cue eval root.cue cmp stderr import_stderr.golden ! exec cue eval mod.com/x cmp stderr absolute_stderr.golden ! exec cue eval ./x # TODO: it would be nice if the error output was similar for this case as the others. stderr 'found packages "y" \(y.cue\) and "z" \(z.cue\) in ".*"' -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- root.cue -- package root import "mod.com/x" x -- x/y.cue -- package y y: 5 -- x/z.cue -- package z z: 5 -- import_stderr.golden -- import failed: cannot find package "mod.com/x": no files in package directory with package name "x": ./root.cue:3:8 -- absolute_stderr.golden -- cannot find package "mod.com/x": no files in package directory with package name "x" pkg_resolution_multiple_packages_one_matching_path_element.txtar000066400000000000000000000014011474664451600367550ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script# Test that a relative package path functions the same as an absolute package path # when there are multiple packages in the directory where one has a name # that does matches the final element of the import path. exec cue eval root.cue cmp stdout stdout.golden exec cue eval mod.com/x cmp stdout stdout.golden # TODO: the following command fails unexpectedly although it should be consistent with the above. ! exec cue eval ./x stderr 'found packages "x" \(x.cue\) and "y" \(y.cue\) in ".*script-pkg_resolution_multiple_packages_one_matching_path_element.*"' -- stdout.golden -- x: 5 -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- root.cue -- package root import "mod.com/x" x -- x/x.cue -- package x x: 5 -- x/y.cue -- package y y: 5 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/pkg_resolution_path_element_invalid_ident.txtar000066400000000000000000000022551474664451600334510ustar00rootroot00000000000000# Test that a package qualifier is always required to import a package where # the final element of the import path is not a valid CUE identifier. # When there's a qualifier, the import is OK. exec cue eval ./test1/root.cue cmp stdout stdout.golden exec cue eval mod.com/1x:x cmp stdout stdout.golden exec cue eval ./1x:x cmp stdout stdout.golden # Without a qualifier, it's an error because the chosen package is ambiguous # (the package clause in CUE has to declare a valid CUE identifier). ! exec cue eval ./test2/root.cue cmp stderr test2-import-stderr.golden ! exec cue eval mod.com/1x cmp stderr test2-abs-stderr.golden # TODO: the following succeeds inappropriately exec cue eval ./1x -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- test1/root.cue -- package test1 import "mod.com/1x:x" x -- test2/root.cue -- package test1 import "mod.com/1x" x -- 1x/x.cue -- package x x: 5 -- stdout.golden -- x: 5 -- test2-import-stderr.golden -- import failed: cannot determine package name for "mod.com/1x"; set it explicitly with ':': ./test2/root.cue:3:8 -- test2-abs-stderr.golden -- cannot determine package name for "mod.com/1x"; set it explicitly with ':' pkg_resolution_single_package_matching_path_element.txtar000066400000000000000000000014471474664451600353710ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script# Test that a relative package path functions the same as an absolute package path # when there is a single package in the directory with a name # that matches the final element of the import path. exec cue eval root.cue cmp stdout output.golden exec cue eval mod.com/x cmp stdout output.golden exec cue eval ./x cmp stdout output.golden # Also test that the above all works when using an explicit qualifier. exec cue eval root_qualifier.cue cmp stdout output.golden exec cue eval mod.com/x:x cmp stdout output.golden exec cue eval ./x:x cmp stdout output.golden -- output.golden -- x: 5 -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- root.cue -- package root import "mod.com/x" x -- root_qualifier.cue -- package root import "mod.com/x:x" x -- x/y.cue -- package x x: 5 pkg_resolution_single_package_not_matching_path_element.txtar000066400000000000000000000015331474664451600362450ustar00rootroot00000000000000cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script# Test that a relative package path functions the same as an absolute package path # when there is a single package in the directory with a name # that does not match the final element of the import path. ! exec cue eval root.cue cmp stderr import_stderr.golden ! exec cue eval mod.com/x cmp stderr absolute_stderr.golden # TODO: the following command succeeds unexpectedly, # although it should be consistent with the above. exec cue eval ./x -- cue.mod/module.cue -- module: "mod.com" language: version: "v0.9.0" -- root.cue -- package root import "mod.com/x" x -- x/y.cue -- package y y: 5 -- import_stderr.golden -- import failed: cannot find package "mod.com/x": no files in package directory with package name "x": ./root.cue:3:8 -- absolute_stderr.golden -- cannot find package "mod.com/x": no files in package directory with package name "x" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/pprof.txtar000066400000000000000000000014271474664451600241150ustar00rootroot00000000000000# Grab a CPU profile and check that it's valid. exec cue eval --cpuprofile cpu.out x.cue go tool pprof -top cpu.out stdout 'Type: cpu' # Grab an allocation profile and check that it's valid. exec cue eval --memprofile mem.out x.cue go tool pprof -top mem.out stdout 'Type: inuse_space' # Both flags can be used at the same time. rm cpu.out mem.out exec cue eval --cpuprofile=cpu.out --memprofile=mem.out x.cue exists cpu.out exists mem.out # The flags should still work with 'cue cmd', which runs a command within a command. rm cpu.out exec cue cmd --cpuprofile=cpu.out hello go tool pprof -top cpu.out stdout 'Type: cpu' -- x.cue -- package p a: 1 b: 2 c: a | b message: "World" -- x_tool.cue -- package p import "tool/cli" command: hello: cli.Print & { text: "Hello \(message)" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_auth.txtar000066400000000000000000000035451474664451600256630ustar00rootroot00000000000000# Test that we can authenticate to a registry with basic auth. env DOCKER_CONFIG=$WORK/dockerconfig env-fill $DOCKER_CONFIG/config.json exec cue export . cmp stdout expect-stdout # Sanity-check that we get an error when using the wrong password. rm $CUE_CACHE_DIR env-fill dockerconfig/badpassword.json cp dockerconfig/badpassword.json dockerconfig/config.json ! exec cue export . stderr 'import failed: cannot find package "example.com/e": cannot fetch example.com/e@v0.0.1: module example.com/e@v0.0.1: 401 Unauthorized: unauthorized: authentication required: invalid user-password credentials' # Sanity-check that a configured default helper which is not installed # is not treated as a fatal error. See https://cuelang.org/issue/2934. rm $CUE_CACHE_DIR env-fill dockerconfig/missing_default_helper.json cp dockerconfig/missing_default_helper.json dockerconfig/config.json exec cue export . cmp stdout expect-stdout -- dockerconfig/config.json -- { "auths": { "${DEBUG_REGISTRY_HOST}": { "username": "someone", "password": "something" } } } -- dockerconfig/badpassword.json -- { "auths": { "${DEBUG_REGISTRY_HOST}": { "username": "someone", "password": "wrongpassword" } } } -- dockerconfig/missing_default_helper.json -- { "credsStore": "definitely-not-found-executable", "auths": { "${DEBUG_REGISTRY_HOST}": { "username": "someone", "password": "something" } } } -- expect-stdout -- "ok" -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- _registry/auth.json -- {"username": "someone", "password": "something"} -- _registry_prefix -- somewhere/other -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "ok" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_auth_logins.txtar000066400000000000000000000052551474664451600272360ustar00rootroot00000000000000# Test that we can authenticate to a registry with bearer token auth via logins.json. # We use multiple dependencies to test concurrent fetches as well, to catch races. env CUE_CONFIG_DIR=$WORK/cueconfig env-fill $CUE_CONFIG_DIR/logins.json exec cue export . cmp stdout expect-stdout # Sanity-check that we get an error when using the wrong token. env CUE_CACHE_DIR=$WORK/.tmp/different-cache env-fill cueconfig/badtoken.json cp cueconfig/badtoken.json cueconfig/logins.json ! exec cue export . stderr 'import failed: cannot find package .* 401 Unauthorized: unauthorized: authentication required: invalid bearer credentials' # An invalid logins.json should result in an immediate error. env CUE_CONFIG_DIR=$WORK/badconfig ! exec cue export . stderr 'cannot load CUE registry logins: json: cannot unmarshal string into Go struct field' # Setting CUE_CONFIG_DIR to an empty directory should still try Docker auth. # Note that Docker auth fails entirely, but we don't refuse to continue without a logins.json. env CUE_CONFIG_DIR=$WORK/emptyconfig mkdir $CUE_CONFIG_DIR ! exec cue export . stderr 'module example.com/e1@v0.0.1: cannot do HTTP request' # If no CUE_CONFIG_DIR is set and we can't find its default location, # we should still carry on with Docker auth assuming that logins.json does not exist. env HOME= CUE_CONFIG_DIR= exec env ! exec cue export . stderr 'module example.com/e1@v0.0.1: cannot do HTTP request' -- cueconfig/logins.json -- { "registries": { "${DEBUG_REGISTRY_HOST}": { "access_token": "goodtoken" } } } -- cueconfig/badtoken.json -- { "registries": { "${DEBUG_REGISTRY_HOST}": { "access_token": "badtoken" } } } -- badconfig/logins.json -- {"registries": "unexpected json"} -- expect-stdout -- [ "ok1", "ok2", "ok3" ] -- main.cue -- package main import "example.com/e1" import "example.com/e2" import "example.com/e3" [e1.foo, e2.foo, e3.foo] -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e1": v: "v0.0.1" deps: "example.com/e2": v: "v0.0.1" deps: "example.com/e3": v: "v0.0.1" -- _registry/auth.json -- {"bearerToken": "goodtoken"} -- _registry_prefix -- somewhere/other -- _registry/example.com_e1_v0.0.1/cue.mod/module.cue -- module: "example.com/e1@v0" language: version: "v0.8.0" -- _registry/example.com_e1_v0.0.1/main.cue -- package e1 foo: "ok1" -- _registry/example.com_e2_v0.0.1/cue.mod/module.cue -- module: "example.com/e2@v0" language: version: "v0.8.0" -- _registry/example.com_e2_v0.0.1/main.cue -- package e2 foo: "ok2" -- _registry/example.com_e3_v0.0.1/cue.mod/module.cue -- module: "example.com/e3@v0" language: version: "v0.8.0" -- _registry/example.com_e3_v0.0.1/main.cue -- package e3 foo: "ok3" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_import_with_no_modfile.txtar000066400000000000000000000005651474664451600314610ustar00rootroot00000000000000! exec cue export x.cue cmp stderr want-stderr -- want-stderr -- import failed: imports are unavailable because there is no cue.mod/module.cue file: ./x.cue:1:8 -- x.cue -- import "foo.com/bar" x: bar.X -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_invalid_env.txtar000066400000000000000000000005611474664451600272130ustar00rootroot00000000000000env CUE_REGISTRY=malformed!registry@url ! exec cue eval . cmp stderr expect-stderr -- expect-stderr -- bad value for $CUE_REGISTRY: invalid registry "malformed!registry@url": invalid host name "malformed!registry@url" in registry -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" deps: "example.com/e": v: "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_lazy_config.txtar000066400000000000000000000025471474664451600272270ustar00rootroot00000000000000# Test that a bad docker config file isn't a problem until we actually # need to talk to a registry. # Initially the code doesn't use any modules, so there should # be no need to use a registry. env DOCKER_CONFIG=$WORK/dockerconfig exec cue export . cmp stdout expect-stdout # The new code uses modules, so we should get a warning # when the config file is read. cp OTHER/main.cue main.cue cp OTHER/cue.mod/module.cue cue.mod/module.cue ! exec cue export . stderr '^test.org@v0: import failed: cannot find package "example.com/e": cannot fetch example.com/e@v0.0.1: module example.com/e@v0.0.1: cannot do HTTP request: Get ".*": cannot load OCI auth configuration: invalid config file ".*config.json": decode failed: .*' -- dockerconfig/config.json -- should be JSON but isn't -- expect-stdout -- "ok" -- main.cue -- package main "ok" -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" -- OTHER/main.cue -- package main import "example.com/e" e.foo -- OTHER/cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- _registry/auth.json -- {"username": "someone", "password": "something"} -- _registry_prefix -- somewhere/other -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "ok" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_local_import_not_found.txtar000066400000000000000000000006711474664451600314560ustar00rootroot00000000000000# TODO: this evaluation should work OK. exec cue eval . cmp stdout expect-stdout -- expect-stdout -- x: 5 -- cue.mod/module.cue -- module: "main.org/foo@v0" language: version: "v0.8.0" -- foo.cue -- package foo import "main.org/foo/bar" bar -- bar/bar.cue -- package bar x: 5 -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_module_not_found.txtar000066400000000000000000000013231474664451600302520ustar00rootroot00000000000000! exec cue eval . # TODO this error message could use improvement: # - the "error response: 404 Not Found: " part is redundant # - the module path is also repeated redundantly. cmp stderr expect-stderr -- expect-stderr -- test.org@v0: import failed: cannot find package "example.com/e": cannot fetch example.com/e@v0.0.2: module example.com/e@v0.0.2: module not found: ./main.cue:2:8 -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.2" -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_mux.txtar000066400000000000000000000100111474664451600255150ustar00rootroot00000000000000# Check that the registry multiplexing can be specified in the simple format. env CUE_REGISTRY=${CUE_REGISTRY1},baz.org=$DEBUG_REGISTRY2_HOST/foo/bar+insecure exec cue eval . cmp stdout expect-stdout # Check that it also works with the "simple:" prefix. env CUE_REGISTRY=simple:${CUE_REGISTRY1},baz.org=$DEBUG_REGISTRY2_HOST/foo/bar+insecure exec cue eval . cmp stdout expect-stdout # Check that we can specify it as a file. env-fill _config/registry_config.cue env CUE_REGISTRY=file:_config/registry_config.cue exec cue eval . cmp stdout expect-stdout # Check that the configuration data can be passed directly in the env var. env CUE_REGISTRY='inline:defaultRegistry: registry: "'${CUE_REGISTRY1}'", moduleRegistries: "baz.org": registry: "'${CUE_REGISTRY2}'"' exec cue eval . cmp stdout expect-stdout -- _config/registry_config.cue -- defaultRegistry: registry: "${CUE_REGISTRY1}" moduleRegistries: "baz.org": registry: "${CUE_REGISTRY2}" -- expect-stdout -- "foo.com/bar/hello@v0": "v0.2.3" "bar.com@v0": "v0.5.0" "baz.org@v0": "v0.10.1 in registry2" main: "main" "example.com@v0": "v0.0.1" -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.10.1" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- main.cue -- package main import "example.com@v0:main" main -- _registry2_prefix -- foo/bar -- _registry1/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" deps: { "foo.com/bar/hello@v0": v: "v0.2.3" "bar.com@v0": v: "v0.5.0" } -- _registry1/example.com_v0.0.1/top.cue -- package main // Note: import without a major version takes // the major version from the module.cue file. import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry1/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry1/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry1/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry1/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry1/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry1/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry1/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry1/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry1/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry1/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" -- _registry2/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry2/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0 in registry2" -- _registry2/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1 in registry2" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_mux_auth.txtar000066400000000000000000000073641474664451600265570ustar00rootroot00000000000000# Test that authorization works when there are two # registries that both require different credentials. env CUE_REGISTRY=${CUE_REGISTRY1},baz.org=$CUE_REGISTRY2 env DOCKER_CONFIG=$WORK/dockerconfig env-fill $DOCKER_CONFIG/config.json exec cue eval . cmp stdout expect-stdout -- expect-stdout -- "foo.com/bar/hello@v0": "v0.2.3" "bar.com@v0": "v0.5.0" "baz.org@v0": "v0.10.1 in registry2" main: "main" "example.com@v0": "v0.0.1" -- dockerconfig/config.json -- { "auths": { "${DEBUG_REGISTRY1_HOST}": { "username": "registry1user", "password": "registry1password" }, "${DEBUG_REGISTRY2_HOST}": { "username": "registry2user", "password": "registry2password" } } } -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.10.1" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- main.cue -- package main import "example.com@v0:main" main -- _registry1/auth.json -- {"username": "registry1user", "password": "registry1password"} -- _registry1/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" deps: { "foo.com/bar/hello@v0": v: "v0.2.3" "bar.com@v0": v: "v0.5.0" } -- _registry1/example.com_v0.0.1/top.cue -- package main // Note: import without a major version takes // the major version from the module.cue file. import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry1/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry1/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry1/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry1/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry1/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry1/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry1/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry1/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry1/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry1/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry1/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" -- _registry2/auth.json -- {"username": "registry2user", "password": "registry2password"} -- _registry2/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry2/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0 in registry2" -- _registry2/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry2/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1 in registry2" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_nofallback.txtar000066400000000000000000000012411474664451600270050ustar00rootroot00000000000000# Check that we can explicitly avoid falling back to the default registry. env CUE_REGISTRY=foo.com=$CUE_REGISTRY1,none ! exec cue eval . cmp stderr expect-stderr -- expect-stderr -- main.org@v0: import failed: cannot find package "example.com@v0": cannot fetch example.com@v0.0.1: module not found: ./main.cue:2:8 -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" deps: { "example.com@v0": { v: "v0.0.1" } } -- main.cue -- package main import "example.com@v0:main" main -- _registry1/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry1/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_prefix.txtar000066400000000000000000000007251474664451600262140ustar00rootroot00000000000000exec cue export . cmp stdout expect-stdout -- expect-stdout -- "ok" -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.9.0-alpha.0" deps: "example.com/e": v: "v0.0.1" -- _registry_prefix -- somewhere/other -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.9.0-alpha.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "ok" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish.txtar000066400000000000000000000060261474664451600263650ustar00rootroot00000000000000# Check that we can use the cue mod publish command to publish to a registry. memregistry MEMREGISTRY env ORIG_CUE_REGISTRY=$CUE_REGISTRY env CUE_REGISTRY=example.com=$MEMREGISTRY+insecure,$CUE_REGISTRY cd example exec cue mod publish v0.0.1 stdout '^published example.com@v0.0.1 to [^ ]+/example.com:v0.0.1$' cd ../main exec cue eval . cmp stdout ../expect-eval-stdout # Sanity check that the module isn't present in the fallback registry. env CUE_REGISTRY=$ORIG_CUE_REGISTRY env CUE_CACHE_DIR=$WORK/.tmp/different-cache ! exec cue eval stderr 'cannot fetch example.com@v0.0.1: module example.com@v0.0.1: module not found' -- expect-eval-stdout -- "foo.com/bar/hello@v0": "v0.2.3" "bar.com@v0": "v0.5.0" "baz.org@v0": "v0.10.1" main: "main" "example.com@v0": "v0.0.1" -- main/cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" deps: { "bar.com@v0": v: "v0.5.0" "baz.org@v0": v: "v0.10.1" "example.com@v0": v: "v0.0.1" "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- main/main.cue -- package main import "example.com@v0:main" main -- example/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" deps: { "bar.com@v0": v: "v0.5.0" "baz.org@v0": v: "v0.10.1" "foo.com/bar/hello@v0": v: "v0.2.3" } -- example/top.cue -- package main // Note: import without a major version takes // the major version from the module.cue file. import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish_auth.txtar000066400000000000000000000017711474664451600274100ustar00rootroot00000000000000# Check that we can use the cue mod publish command to publish to a registry # that's protected by authorization. memregistry -auth=foo:bar MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY+insecure env DOCKER_CONFIG=$WORK/dockerconfig env-fill $DOCKER_CONFIG/config.json cd example exec cue mod publish v0.0.1 stdout '^published example.com@v0.0.1 to [^ ]+/example.com:v0.0.1$' cd ../main exec cue eval . cmp stdout ../expect-eval-stdout -- dockerconfig/config.json -- { "auths": { "${MEMREGISTRY}": { "username": "foo", "password": "bar" } } } -- expect-eval-stdout -- "example.com@v0": "v0.0.1" main: "main" -- main/cue.mod/module.cue -- module: "main.org" language: version: "v0.9.0-alpha.0" deps: "example.com@v0": v: "v0.0.1" -- main/main.cue -- package main import "example.com@v0:main" main "main": "main" -- example/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" -- example/top.cue -- package main "example.com@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish_idempotent.txtar000066400000000000000000000047211474664451600306150ustar00rootroot00000000000000# Check that cue mod publish is idempotent for all sources. # # We first perform the check on a 'source: kind: "self"' module, before reusing # that same module but with 'source: kind: "git"' for later versions. # # These checks rely on two critical properties of the in-memory OCI server: # # 1. the in-memory OCI server is run in immutable mode # 2. the in-memory OCI server accepts an attempt to publish a module under an # existing tag, but only in the case that the modules digest is identical. # # If point 1 were not true, then we would get a false positive from this check, # i.e. we would fail to detect that 'cue mod publish' is not idempotent. If, # separately, point 2 were not true, then we would get a failure as a result of # the follow 'republish' attempt, even if the published module digest were # identicial. # # We ensure point 1 is the case by asserting that we get an error when we # attempt to republish to an existing version of a module when we know the # contents to be different. # # If we fall foul of the failure as a result of point 2 not being true, this # series of tests will fail. We will then be forced to move this test to a # different place, which is perhaps where it belongs given the length of this # explanatory comment. memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY # v0.0.1 - source.kind == "self" cd $WORK/example cp $WORK/v0.0.1 $WORK/example/root.cue exec cue mod publish --json v0.0.1 stdin stdout exec cue export -e files json: - cmp stdout $WORK/filelist.golden exec cue mod publish v0.0.1 exec cue mod publish v0.0.1 # idempotent check # v0.0.2 - source.kind == "git" [!exec:git] skip 'no git command found' exec cue mod edit --source git cp $WORK/v0.0.2 $WORK/example/root.cue exec git init . exec git add . exec git -c user.name=noone -c user.email=noone@example.com commit -m 'initial commit' # Verify we cannot overwrite v0.0.1 with what we know is different module # contents. This ensures the in-memory OCI server is run in immutable mode. ! exec cue mod publish v0.0.1 stderr 'cannot overwrite tag' exec cue mod publish --json v0.0.2 stdin stdout exec cue export -e files json: - cmp stdout $WORK/filelist.golden exec cue mod publish v0.0.2 exec cue mod publish v0.0.2 # idempotent check -- filelist.golden -- [ "cue.mod/module.cue", "root.cue" ] -- v0.0.1 -- package root v: "v0.0.1" -- v0.0.2 -- package root v: "v0.0.2" -- example/cue.mod/module.cue -- module: "x.example/root@v0" language: version: "v0.9.0-alpha.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish_json.txtar000066400000000000000000000012631474664451600274140ustar00rootroot00000000000000# Check that we can use the cue mod publish command to # print information about the module to be published in JSON # format cd example exec cue mod publish --json v0.0.1 cp stdout $WORK/got.json # Note: use a CUE schema here because we don't # to hard-code the exact result. cd $WORK exec cue vet got.json want.cue -- want.cue -- #schema: { version!: "example.com@v0.0.1" ref!: =~ "^registry.cue.works/example.com:v0.0.1@sha256:[a-f0-9]+$" files!: [ "cue.mod/module.cue", "foo.cue", ] } #schema -- example/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" -- example/foo.cue -- package foo "example.com/foo@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish_non_root.txtar000066400000000000000000000007521474664451600303020ustar00rootroot00000000000000# Check that we can use the cue mod publish command to publish to a registry # with a repository prefix. memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY/some/repo+insecure cd example/foo exec cue mod publish v0.0.1 stdout '^published example.com@v0.0.1 to [^ ]+/some/repo/example.com:v0.0.1$' -- example/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" -- example/foo/foo.cue -- package foo "example.com/foo@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish_to_image.txtar000066400000000000000000000010051474664451600302210ustar00rootroot00000000000000# Check that we can use the cue mod publish command to create an # OCI image. exec cue mod publish --out $WORK/image v0.0.1 stdout '^wrote image for example.com@v0.0.1 to .*/image$' cmp $WORK/image/oci-layout $WORK/want-oci-layout exists $WORK/image/index.json exists $WORK/image/blobs -- want-oci-layout -- { "imageLayoutVersion": "1.0.0" } -- cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" -- foo.cue -- package foo "example.com/foo@v0": "v0.0.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_publish_with_git.txtar000066400000000000000000000115301474664451600302570ustar00rootroot00000000000000# Check that we can use the cue mod publish command to publish to a registry # using the git VCS, and that it doesn't publish files that are git-ignored. [!exec:git] skip 'no git command found' memregistry MEMREGISTRY env CUE_REGISTRY=$MEMREGISTRY cd $WORK/example exec git init . exec git add . exec git -c user.name=noone -c user.email=noone@example.com commit -m 'initial commit' # Publish the root module cd $WORK/example exec cue mod publish v0.0.1 stdout '^published x.example/root@v0.0.1 to [^ ]+/x.example/root:v0.0.1$' # Now remove a file that's outside the root/a or root/b directory, which makes # the git repository unclean but the module subdirectories remain clean. rm $WORK/example/otherfile cd $WORK/example/a exec cue mod publish --json v0.0.1 stdin stdout exec cue export -e files json: - cmp stdout $WORK/expect-root-a-files exec cue mod publish v0.0.1 stdout '^published x.example/root/a@v0.0.1 to [^ ]+/x.example/root/a:v0.0.1$' cd $WORK/example/b # Modify the root LICENSE and verify that we cannot publish root/b in this # state (root/b does not have a LICENSE and so we should expect it to find the # root LICENSE, but fail because it's unclean). cp $WORK/example/LICENSE $WORK/example/LICENSE.golden mv $WORK/example/LICENSE.modified $WORK/example/LICENSE ! exec cue mod publish v0.0.1 stderr 'VCS state is not clean for '..\${/}LICENSE # Restore the root LICENSE file and actually publish cp $WORK/example/LICENSE.golden $WORK/example/LICENSE exec cue mod publish --json v0.0.1 stdin stdout exec cue export -e files json: - cmp stdout $WORK/expect-root-b-files exec cue mod publish v0.0.1 stdout '^published x.example/root/b@v0.0.1 to [^ ]+/x.example/root/b:v0.0.1$' # Verify that we can evaluate based on those dependencies cd $WORK/main exec cue eval . cmp stdout ../expect-eval-stdout # Verify that we have a LICENSE files for all modules cmp ${CUE_CACHE_DIR}/mod/extract/x.example/root@v0.0.1/LICENSE $WORK/example/LICENSE cmp ${CUE_CACHE_DIR}/mod/extract/x.example/root/a@v0.0.1/LICENSE $WORK/example/a/LICENSE cmp ${CUE_CACHE_DIR}/mod/extract/x.example/root/b@v0.0.1/LICENSE $WORK/example/LICENSE # Check that the manifest contains the expected git metadata # Note: we use cue vet rather than cmp because the # manifest contains information that's tricky to control/predict # in a test, such as git commit times and commit hashes. get-manifest $MEMREGISTRY/x.example/root:v0.0.1 $WORK/manifest0.json exec cue vet $WORK/manifest-schema.cue $WORK/manifest0.json # If the git directory is not clean, the publish should fail. We can # conveniently combine that check with the .gitignore removal. cd $WORK/example rm .gitignore cd $WORK/example/a ! exec cue mod publish v0.0.2 cmp stderr $WORK/expect-unclean-stderr # Sanity check that once the .gitignore file has been removed, the # published module does actually contain the ignored content. cd $WORK/example exec git add . exec git -c user.name=noone -c user.email=noone@example.com commit -m 'commit with no .gitignore' cd $WORK/example/a exec cue mod publish v0.0.2 cd $WORK/main exec cue mod get x.example/root/a@v0.0.2 exec cue eval . cmp stdout $WORK/expect-eval-stdout2 -- expect-root-a-files -- [ "LICENSE", "a.cue", "cue.mod/module.cue" ] -- expect-root-b-files -- [ "LICENSE", "b.cue", "cue.mod/module.cue" ] -- manifest-schema.cue -- import "time" annotations!: { "org.cuelang.vcs-type"!: "git" "org.cuelang.vcs-commit-time"!: time.Time "org.cuelang.vcs-commit"!: =~"^[a-f0-9]+$" } -- expect-publish-stdout -- published x.example/e@v0.0.1 -- expect-eval-stdout -- root: true a: true b: true -- expect-unclean-stderr -- VCS state is not clean -- expect-eval-stdout2 -- root: true a: true sensitive_a: true b: true -- main/cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.9.0-alpha.0" source: kind: "self" deps: "x.example/root@v0": v: "v0.0.1" deps: "x.example/root/a@v0": v: "v0.0.1" deps: "x.example/root/b@v0": v: "v0.0.1" -- main/main.cue -- package main import ( "x.example/root@v0" "x.example/root/a@v0" "x.example/root/b@v0" ) root a b -- example/.gitignore -- /a/ignored.cue -- example/cue.mod/module.cue -- module: "x.example/root@v0" language: version: "v0.9.0-alpha.0" source: kind: "git" -- example/LICENSE -- root LICENSE -- example/LICENSE.modified -- modified root LICENSE -- example/root.cue -- package root root: true -- example/a/cue.mod/module.cue -- module: "x.example/root/a@v0" language: version: "v0.9.0-alpha.0" source: kind: "git" -- example/a/LICENSE -- a LICENSE -- example/a/a.cue -- package a a: true -- example/a/ignored.cue -- package a sensitive_a: true -- example/b/cue.mod/module.cue -- module: "x.example/root/b@v0" language: version: "v0.9.0-alpha.0" source: kind: "git" -- example/b/b.cue -- package b b: true -- example/otherfile -- this will be removed but is outside the module so that shouldn't stop the publish working. cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_resolve.txtar000066400000000000000000000033151474664451600263740ustar00rootroot00000000000000env CUE_REGISTRY=foo.com/bar=myregistry.example/foo,other.org=none exec cue mod resolve somethingelse.bar.com/abc@v1.2.3 cmp stdout want-resolve0 exec cue mod resolve somethingelse.bar.com/abc cmp stdout want-resolve1 exec cue mod resolve foo.com/bar/baz@v0.1.2 cmp stdout want-resolve2 ! exec cue mod resolve other.org/a/b cmp stderr want-resolve3 env CUE_REGISTRY=file:registry-config.cue exec cue mod resolve a.com/b cmp stdout want-resolve4 exec cue mod resolve a.com/foo/bar/baz@v1.2.3 cmp stdout want-resolve5 exec cue mod resolve a.com/foo/bar/baz@v1.2.3 cmp stdout want-resolve5 exec cue mod resolve stripped.org/bar/baz/p@v0.1.2 cmp stdout want-resolve6 exec cue mod resolve cmp stdout want-resolve7 exec cue mod resolve . cmp stdout want-resolve7 -- cue.mod/module.cue -- module: "a.com/foo/bar" language: version: "v0.9.2" -- registry-config.cue -- moduleRegistries: { "a.com": { registry: "r1.example/a/b+insecure" } "a.com/foo/bar": { registry: "r2.example/xxx" pathEncoding: "hashAsRepo" prefixForTags: "cue-" } "stripped.org/bar": { registry: "r3.example/repo" stripPrefix: true } "badmodules.org": { registry: "none" } } -- want-resolve0 -- registry.cue.works/somethingelse.bar.com/abc:v1.2.3 -- want-resolve1 -- registry.cue.works/somethingelse.bar.com/abc -- want-resolve2 -- myregistry.example/foo/foo.com/bar/baz:v0.1.2 -- want-resolve3 -- no registry found for module "other.org/a/b" -- want-resolve4 -- r1.example/a/b/a.com/b -- want-resolve5 -- r2.example/xxx/0764601cd4e1d9d84efc2f4ddc23191e599fa9826f46b16b84269b6fe3679184:cue-v1.2.3 -- want-resolve6 -- r3.example/repo/baz/p:v0.1.2 -- want-resolve7 -- r2.example/xxx/7c9813cd44d6d9348eb223e71d608e491805730547b8ff6f4b1ccb964b913148 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_simple.txtar000066400000000000000000000054011474664451600262040ustar00rootroot00000000000000exec cat cue.mod/module.cue exec cue eval . cmp stdout expect-stdout # Check that other commands work with modules too. exec cue export . cmp stdout expect-stdout-json exec cue trim . exec cue vet . exec cue fmt . -- expect-stdout -- "foo.com/bar/hello@v0": "v0.2.3" "bar.com@v0": "v0.5.0" "baz.org@v0": "v0.10.1" main: "main" "example.com@v0": "v0.0.1" -- expect-stdout-json -- { "foo.com/bar/hello@v0": "v0.2.3", "bar.com@v0": "v0.5.0", "baz.org@v0": "v0.10.1", "main": "main", "example.com@v0": "v0.0.1" } -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" deps: { "bar.com@v0": { v: "v0.5.0" } "baz.org@v0": { v: "v0.10.1" } "example.com@v0": { v: "v0.0.1" } "foo.com/bar/hello@v0": { v: "v0.2.3" default: true } } -- main.cue -- package main import "example.com@v0:main" main -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" deps: { "foo.com/bar/hello@v0": v: "v0.2.3" "bar.com@v0": v: "v0.5.0" } -- _registry/example.com_v0.0.1/top.cue -- package main // Note: import without a major version takes // the major version from the module.cue file. import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_submodule.txtar000066400000000000000000000014471474664451600267200ustar00rootroot00000000000000# This test tests that submodules work OK. exec cue eval . cmp stdout expect-stdout -- expect-stdout -- a: { e: true f: true } -- cue.mod/module.cue -- module: "main.org" language: version: "v0.8.0" deps: { "example.com@v0": { default: true v: "v0.0.1" } "example.com/foo@v0": { default: true v: "v0.0.1" } } -- main.cue -- package main import ( "example.com@v0:example" "example.com/foo@v0" ) a: { e: example.e f: foo.f } -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package example e: true -- _registry/example.com_foo_v0.0.1/cue.mod/module.cue -- module: "example.com/foo@v0" language: version: "v0.8.0" -- _registry/example.com_foo_v0.0.1/foo.cue -- package foo f: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_token_auth.txtar000066400000000000000000000014611474664451600270560ustar00rootroot00000000000000# Test that we can authenticate to a registry using # a token server for authentication. env DOCKER_CONFIG=$WORK/dockerconfig env-fill $DOCKER_CONFIG/config.json env CUE_DEBUG=http exec cue export . cmp stdout expect-stdout -- dockerconfig/config.json -- { "auths": { "${DEBUG_REGISTRY_HOST}": { "identitytoken": "registrytest-refresh" } } } -- expect-stdout -- "ok" -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- _registry/auth.json -- { "useTokenServer": true } -- _registry_prefix -- somewhere/other -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "ok" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_token_auth_tidy.txtar000066400000000000000000000015251474664451600301100ustar00rootroot00000000000000# Test that we can use cue mod tidy on a registry that # responds with 403 (forbidden) status codes # for some registry repositories. env DOCKER_CONFIG=$WORK/dockerconfig env-fill $DOCKER_CONFIG/config.json env CUE_DEBUG=http exec cue mod tidy exec cue export . cmp stdout expect-stdout -- dockerconfig/config.json -- { "auths": { "${DEBUG_REGISTRY_HOST}": { "identitytoken": "registrytest-refresh" } } } -- expect-stdout -- "ok" -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" -- _registry/auth.json -- { "useTokenServer": true, "acl": { "allow": ["^example\\.com/e$"] } } -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "ok" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_with_empty_module_path.txtar000066400000000000000000000005031474664451600314630ustar00rootroot00000000000000exec cue export x.cue cmp stdout want-stdout -- want-stdout -- { "a": 1 } -- cue.mod/module.cue -- module: "" language: version: "v0.8.0" -- x.cue -- a: 1 -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_with_no_modfile.txtar000066400000000000000000000004031474664451600300560ustar00rootroot00000000000000exec cue export x.cue cmp stdout want-stdout -- want-stdout -- { "a": 1 } -- x.cue -- a: 1 -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" -- _registry/example.com_v0.0.1/top.cue -- package main cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_with_pkg.txtar000066400000000000000000000027731474664451600265400ustar00rootroot00000000000000# When CUE_REGISTRY is correctly set, packages in the # pkg, usr and gen directories will be used when they don't conflict with # other module dependencies. exec cue export . cmp stdout expect-stdout -- expect-stdout -- { "e": { "a": { "remote": true } }, "local_pkg": { "a": { "pkg": true } }, "local_pkg_usr": { "a": { "pkg": true, "usr": true } }, "local_gen_usr": { "a": { "gen": true, "usr": true } } } -- main.cue -- package main import ( "example.com/e" local_pkg "example.com/e/local_pkg:x" local_pkg_usr "example.com/e/local_pkg_usr:x" local_gen_usr "example.com/e/local_gen_usr:x" ) "e": e "local_pkg": local_pkg "local_pkg_usr": local_pkg_usr "local_gen_usr": local_gen_usr -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- cue.mod/pkg/example.com/e/local_pkg/x.cue -- package x a: pkg: true -- cue.mod/pkg/example.com/e/local_pkg_usr/x.cue -- package x a: pkg: true -- cue.mod/usr/example.com/e/local_pkg_usr/x.cue -- package x a: usr: true -- cue.mod/usr/example.com/e/local_gen_usr/x.cue -- package x a: usr: true -- cue.mod/gen/example.com/e/local_gen_usr/x.cue -- package x a: gen: true -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e a: remote: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_with_pkg_conflict.txtar000066400000000000000000000017051474664451600304130ustar00rootroot00000000000000# When CUE_REGISTRY is correctly set, packages in the # pkg directory will result in an error when they conflict with actual # dependencies. ! exec cue export . cmp stderr expect-stderr -- expect-stderr -- test.org@v0: import failed: cannot find package "example.com/e": ambiguous import: found package example.com/e in multiple modules: example.com/e@v0 v0.0.1 (.) local (cue.mod/pkg/example.com/e): ./main.cue:2:8 -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- cue.mod/pkg/example.com/e/cue.mod/module.cue -- module: "example.com/e" language: version: "v0.8.0" -- cue.mod/pkg/example.com/e/main.cue -- package e foo: "cue.mod/pkg source" -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "registry source" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_with_remote_gen.txtar000066400000000000000000000017731474664451600301020ustar00rootroot00000000000000# This tests what happens when there's a remote module that includes # a gen directory. It's not usable unless a local gen directory is # created too. ! exec cue export . stderr 'import failed: import failed: cannot find package "other.com/p": cannot find module providing package other.com/p:' mkdir cue.mod/gen/other.com/p cp _registry/example.com_e_v0.0.1/gen/other.com/p/p.cue cue.mod/gen/other.com/p exec cue export . cmp stdout expect-stdout -- expect-stdout -- { "e": { "a": { "a": { "p": true } } } } -- main.cue -- package main import "example.com/e" "e": e -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e import "other.com/p" a: p -- _registry/example.com_e_v0.0.1/gen/other.com/p/p.cue -- package p a: p: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/registry_wrong_prefix.txtar000066400000000000000000000011721474664451600274250ustar00rootroot00000000000000env CUE_REGISTRY=$DEBUG_REGISTRY_HOST/something+insecure ! exec cue eval . cmp stderr expect-stderr -- expect-stderr -- test.org@v0: import failed: cannot find package "example.com/e": cannot fetch example.com/e@v0.0.1: module example.com/e@v0.0.1: module not found: ./main.cue:2:8 -- main.cue -- package main import "example.com/e" e.foo -- cue.mod/module.cue -- module: "test.org" language: version: "v0.8.0" deps: "example.com/e": v: "v0.0.1" -- _registry/example.com_e_v0.0.1/cue.mod/module.cue -- module: "example.com/e@v0" language: version: "v0.8.0" -- _registry/example.com_e_v0.0.1/main.cue -- package e foo: "blah" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/sortfields.txtar000066400000000000000000000025041474664451600251420ustar00rootroot00000000000000# Test that CUE_DEBUG=sortfields is wired up correctly. # First, ensure that this debugging option is off by default. exec cue export input.cue cmp stdout export-unsorted.stdout # Turn it on and ensure it works as expected for various commands and encodings. env CUE_DEBUG=sortfields exec cue export input.cue cmp stdout export.stdout exec cue export --out yaml input.cue cmp stdout export-yaml.stdout # TODO: sortfields does not seem to work with def. exec cue def input.cue cmp stdout def.stdout exec cue eval input.cue cmp stdout eval.stdout # Just to double check, ensure it also works for evalv3. env CUE_EXPERIMENT=evalv3 exec cue export input.cue cmp stdout export.stdout # Also ensure that it's wired up for the Go API. stdin input.cue exec cuectx_export cmp stdout export.stdout -- input.cue -- c: true b: { x: true z: true } a: true b: y: true -- export-unsorted.stdout -- { "c": true, "b": { "x": true, "z": true, "y": true }, "a": true } -- export.stdout -- { "a": true, "b": { "x": true, "y": true, "z": true }, "c": true } -- export-yaml.stdout -- a: true b: x: true "y": true z: true c: true -- def.stdout -- c: true b: { x: true y: true z: true } a: true -- eval.stdout -- a: true b: { x: true y: true z: true } c: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/stats.txtar000066400000000000000000000035641474664451600241310ustar00rootroot00000000000000env CUE_TEST_MEMSTATS=memstats.json env CUE_STATS_FILE=stats.json exec cue eval x.cue cmp stats.json out/stats.json # overwrite existing files. env CUE_STATS_FILE=overwrite_stats.json exec cue eval x.cue cmp overwrite_stats.json out/stats.json env CUE_STATS_FILE=stats.cue exec cue eval x.cue cmp stats.cue out/stats.cue env CUE_STATS_FILE=stats.yaml exec cue eval x.cue cmp stats.yaml out/stats.yaml # default output is JSON. env CUE_STATS_FILE=- exec cue eval x.cue cmp stderr out/stderr # Check that EvalVersion reports the correct value. env CUE_STATS_FILE=- env CUE_EXPERIMENT=evalv3=0 exec cue eval x.cue stderr -count=1 '"EvalVersion": 2,' env CUE_EXPERIMENT=evalv3=1 exec cue eval x.cue stderr -count=1 '"EvalVersion": 3,' -- x.cue -- a: 1 b: 2 c: a | b -- memstats.json -- { "TotalAlloc": 300456, "Mallocs": 100123 } -- overwrite_stats.json -- contents overwritten -- out/stats.json -- { "CUE": { "EvalVersion": 2, "Unifications": 4, "Disjuncts": 6, "Conjuncts": 8, "Freed": 6, "Reused": 2, "Allocs": 4, "Retained": 0 }, "Go": { "AllocBytes": 300456, "AllocObjects": 100123 } } -- out/stats.cue -- CUE: { EvalVersion: 2 Unifications: 4 Disjuncts: 6 Conjuncts: 8 Freed: 6 Reused: 2 Allocs: 4 Retained: 0 } Go: { AllocBytes: 300456 AllocObjects: 100123 } -- out/stats.yaml -- CUE: EvalVersion: 2 Unifications: 4 Disjuncts: 6 Conjuncts: 8 Freed: 6 Reused: 2 Allocs: 4 Retained: 0 Go: AllocBytes: 300456 AllocObjects: 100123 -- out/stderr -- { "CUE": { "EvalVersion": 2, "Unifications": 4, "Disjuncts": 6, "Conjuncts": 8, "Freed": 6, "Reused": 2, "Allocs": 4, "Retained": 0 }, "Go": { "AllocBytes": 300456, "AllocObjects": 100123 } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/symlink.txtar000066400000000000000000000046261474664451600244610ustar00rootroot00000000000000[!unix] skip 'no symbolic links available for this test' # This test tests behaviour around symbolic links: # - symbolic links are followed for files that are directly part of the build. # - symbolic links are disallowed for embedded files. # - symbolic links are silently dropped when publishing modules. # TODO this does not test behavior when a zip file contains # a symbolic link, but simple inspection of the modzip.Unzip # code suffices to prove that no symbolic links can be created. # If someone is using their own code to create zip files rather than # modzip (hopefully unlikely) and those zip files contain symbolic # links, then it's their own fault and nothing especially untoward # should happen. # Symbolic link is followed for a single file. symlink y.cue -> x.cue exec cue eval y.cue cmp stdout want-stdout-1 # Symbolic link is followed when part of a package, # including when there are dependencies. symlink z.cue -> _p/z.cue ! exec cue eval stderr 'cannot find package "deps.example/d1"' exec cue mod tidy cmp cue.mod/module.cue want-module exec cue eval cmp stdout want-stdout-2 # Check what happens when a module with symlinks is # published to a registry. memregistry MEMREGISTRY env CUE_REGISTRY=test.example=$MEMREGISTRY+insecure,$CUE_REGISTRY exec cue mod publish v0.0.1 cd _use_main exec cue mod tidy cmp cue.mod/module.cue $WORK/want-module-2 exec cue eval cmp stdout $WORK/want-stdout-3 -- want-stdout-1 -- x: true -- want-module -- module: "test.example/main" language: { version: "v0.9.2" } source: { kind: "self" } deps: { "deps.example/d1@v0": { v: "v0.0.1" default: true } } -- want-module-2 -- module: "test2.example/main" language: { version: "v0.9.2" } deps: { "test.example/main@v0": { v: "v0.0.1" default: true } } -- want-stdout-2 -- x: true z: true dep: { self: "deps.example/d1" } -- want-stdout-3 -- x: true -- cue.mod/module.cue -- module: "test.example/main" language: version: "v0.9.2" source: kind: "self" -- x.cue -- package main x: true -- _p/z.cue -- package main import "deps.example/d1" z: true dep: d1 -- _use_main/main.cue -- package main import "test.example/main" main -- _use_main/cue.mod/module.cue -- module: "test2.example/main" language: version: "v0.9.2" -- _registry/deps.example_d1_v0.0.1/cue.mod/module.cue -- module: "deps.example/d1" language: version: "v0.9.2" -- _registry/deps.example_d1_v0.0.1/x.cue -- package d1 self: "deps.example/d1" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/test_files.txtar000066400000000000000000000032641474664451600251310ustar00rootroot00000000000000# _test.cue files should be ignored apart from for dependency analysis # purposes. Note there is no way to use test files from the command line # currently. exec cue export cmp stdout want-eval # When tidying, the d3 dependency should not appear in the dependencies # because it's only present in a _test.go file in an external # dependency. The d2 dependency _should_ be present, because even though # we don't currently support _test.go files, we still want to consider # them as part of the main module. exec cue mod tidy cmp cue.mod/module.cue want-tidy -- want-eval -- { "x": { "self": "d1" } } -- want-tidy -- module: "test.example/main" language: { version: "v0.9.2" } deps: { "test.example/d1@v0": { v: "v0.0.1" } "test.example/d2@v0": { v: "v0.0.1" default: true } } -- cue.mod/module.cue -- module: "test.example/main" language: version: "v0.9.2" deps: "test.example/d1": v: "v0.0.1" -- main.cue -- package main import "test.example/d1" x: d1 -- main_test.cue -- package main import "test.example/d2" y: d3 -- _registry/test.example_d1_v0.0.1/cue.mod/module.cue -- module: "test.example/d1" language: version: "v0.9.2" -- _registry/test.example_d1_v0.0.1/x.cue -- package d1 self: "d1" -- _registry/test.example_d1_v0.0.1/x_test.cue -- package d1 import "test.example/d3" test: true x: d3 -- _registry/test.example_d2_v0.0.1/cue.mod/module.cue -- module: "test.example/d2" language: version: "v0.9.2" -- _registry/test.example_d2_v0.0.1/x.cue -- package d2 self: "d2" -- _registry/test.example_d3_v0.0.1/cue.mod/module.cue -- module: "test.example/d3" language: version: "v0.9.2" -- _registry/test.example_d3_v0.0.1/x.cue -- package d3 self: "d3" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/toolonly.txtar000066400000000000000000000002631474664451600246430ustar00rootroot00000000000000exec cue cmd foo cmp stdout expect-stdout -- expect-stdout -- foo -- foo_tool.cue -- package foo import "tool/cli" command: foo: task: { foo: cli.Print & { text: "foo" } } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/trim.txtar000066400000000000000000000034551474664451600237450ustar00rootroot00000000000000exec cue trim -o - ./trim cmp stdout expect-stdout -- expect-stdout -- package trim foo: [string]: { _value: string a: 4 b: string d: 8 e: "foo" f: ">> \( _value) <<" n: 5 list: ["foo", 8.0] struct: {a: 3.0} sList: [{a: 8, b: string}, {a: 9, b: *"foo" | string}] rList: [{a: "a"}] rcList: [{a: "a", c: b}] t: [string]: { x: >=0 & <=5 } } foo: bar: { _value: "here" b: "foo" c: 45 sList: [{b: "foo"}, {}] } foo: baz: {} foo: multipath: { t: [string]: { // Combined with the other constraints, we know the value must be 5 and // thus the entry below can be eliminated. x: >=5 & <=8 & int } t: u: {} } group: { for k, v in foo { comp: "\(k)": v } comp: bar: { aa: 8 // new value } comp: baz: {} // TODO: remove: implied by comprehension above } -- trim/trim.cue -- package trim foo: [string]: { _value: string a: 4 b: string d: 8 e: "foo" f: ">> \( _value) <<" n: 5 list: ["foo", 8.0] struct: {a: 3.0} sList: [{a: 8, b: string}, {a: 9, b: *"foo" | string}] rList: [{a: "a"}] rcList: [{a: "a", c: b}] t: [string]: { x: >=0 & <=5 } } foo: bar: { _value: "here" a: 4 b: "foo" c: 45 e: string f: ">> here <<" // 5 is an integer, so this can be removed. n: int struct: {a: 3.0} list: ["foo", float] sList: [{a: 8, b: "foo"}, {b: "foo"}] rList: [{a: string}] rcList: [{a: "a", c: "foo"}] } foo: baz: {} foo: multipath: { t: [string]: { // Combined with the other constraints, we know the value must be 5 and // thus the entry below can be eliminated. x: >=5 & <=8 & int } t: u: { x: 5 } } group: { for k, v in foo { comp: "\(k)": v } comp: bar: { a: 4 aa: 8 // new value } comp: baz: {} // TODO: remove: implied by comprehension above } -- cue.mod/module.cue -- module: "test.example" language: version: "v0.9.0" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/trim_force.txtar000066400000000000000000000006761474664451600251250ustar00rootroot00000000000000# Verify that trim with --force works # First time should simply succeed exec cue trim -o test.cue file.cue cmp test.cue file.cue # Second time will fail without --force ! exec cue trim -o test.cue file.cue stderr 'error writing "test.cue": file already exists' # Second time with --force should succeed exec cue trim --force -o test.cue file.cue cmp test.cue file.cue -- file.cue -- package hello #who: "World" message: "Hello \(#who)!" cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/unknown_args.txtar000066400000000000000000000005511474664451600254770ustar00rootroot00000000000000! exec cue unknown ! stdout . cmp stderr unknown_cmd.out ! exec cue --unknown ! stdout . cmp stderr unknown_flag.out ! exec cue evla ! stdout . cmp stderr typo_cmd.stdout -- unknown_cmd.out -- unknown command "unknown" for "cue" -- unknown_flag.out -- unknown flag: --unknown -- typo_cmd.stdout -- unknown command "evla" for "cue" Did you mean this? eval cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/unknown_filetype_attrval.txtar000066400000000000000000000003141474664451600301160ustar00rootroot00000000000000# Check that we cannot specify an arbitary unknown key-value pair # in a filetype. ! exec cue export cue+foo=bar: x.cue cmp stderr expect-stderr -- x.cue -- true -- expect-stderr -- unknown filetype foo cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/version.txtar000066400000000000000000000013461474664451600244540ustar00rootroot00000000000000# Version output without VCS information. exec cue version stdout -count=1 '^cue version .+' stdout -count=1 '^go version (devel )?go1.' # Version output with VCS information. env CUE_VERSION_TEST_CFG='[{"Key":"vcs","Value":"git"},{"Key":"vcs.revision","Value":"47b7032385cb490fab7d47b89fca36835cf13d39"},{"Key":"vcs.time","Value":"2022-05-10T04:58:46Z"},{"Key":"vcs.modified","Value":"true"}]' exec cue version stdout -count=1 '^cue version .+' stdout -count=1 '^go version (devel )?go1.' stdout -count=1 'vcs git' stdout -count=1 'vcs\.revision 47b7032385cb490fab7d47b89fca36835cf13d39' stdout -count=1 'vcs\.time 2022-05-10T04:58:46Z' stdout -count=1 'vcs\.modified true' stdout -count=1 'cue\.lang\.version '${CUE_LANGUAGE_VERSION@R}'$' cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet.txtar000066400000000000000000000005051474664451600235610ustar00rootroot00000000000000! exec cue vet cmp stderr expect-stderr -- expect-stderr -- some instances are incomplete; use the -c flag to show errors or suppress this message -- partial.cue -- package partial def: *1 | int sum: 1 | 2 b: { idx: a[str] // should resolve to top-level `a` str: string } b: a: b: 4 a: { b: 3 c: 4 } c: b & {str: "b"} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_altdata.txtar000066400000000000000000000006241474664451600252550ustar00rootroot00000000000000exec cue vet schema.cue jsonl: foo.data ! stderr . exec cue export schema.cue jsonl: foo.data cmp stdout export-stdout # Multiple JSON values should be rejected if we're not using jsonl. ! exec cue vet schema.cue json: foo.data stderr 'invalid JSON.*after top-level value' -- schema.cue -- [string]: string -- foo.data -- { "a": "b" } { "c": "d" } -- export-stdout -- { "a": "b", "c": "d" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_concrete.txtar000066400000000000000000000006321474664451600254440ustar00rootroot00000000000000! exec cue vet -c cmp stderr expect-stderr -- expect-stderr -- b.str: incomplete value string: ./partial.cue:8:7 sum: incomplete value 1 | 2 b.idx: invalid non-ground value string (must be concrete string): ./partial.cue:8:7 -- partial.cue -- package partial def: *1 | int sum: 1 | 2 b: { idx: a[str] // should resolve to top-level `a` str: string } b: a: b: 4 a: { b: 3 c: 4 } c: b & {str: "b"} cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_data.txtar000066400000000000000000000015571474664451600245620ustar00rootroot00000000000000! exec cue vet schema.cue data.yaml cmp stderr yaml-stderr ! exec cue export schema.cue data.yaml cmp stderr yaml-stderr # Ensure this also works for other encodings. ! exec cue vet schema.cue data.toml cmp stderr toml-stderr -- schema.cue -- #Language: { tag: string name: =~"^\\p{Lu}" // Must start with an uppercase letter. } languages: [...#Language] -- data.yaml -- languages: - tag: en name: English - tag: nl name: dutch - tag: no name: Norwegian -- data.toml -- [[languages]] name = 'English' tag = 'en' [[languages]] name = 'dutch' tag = 'nl' [[languages]] name = 'Norwegian' tag = 'no' -- yaml-stderr -- languages.1.name: invalid value "dutch" (out of bound =~"^\\p{Lu}"): ./schema.cue:3:8 ./data.yaml:5:11 -- toml-stderr -- languages.1.name: invalid value "dutch" (out of bound =~"^\\p{Lu}"): ./schema.cue:3:8 ./data.toml:5:8 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_disjunction.txtar000066400000000000000000000011251474664451600261710ustar00rootroot00000000000000# vet a.json using #A exec cue vet x.cue justa.cue a.json # vet b.json using #B exec cue vet x.cue justb.cue b.json # Ensure a.json does not vet with #B ! exec cue vet x.cue justb.cue a.json # Ensure b.json does not vet with #A ! exec cue vet x.cue justa.cue b.json # vet a.json using #A | #B exec cue vet x.cue both.cue a.json # vet b.json using #A | #B exec cue vet x.cue both.cue b.json -- a.json -- { "a": "test" } -- b.json -- { "b": 42 } -- both.cue -- package x #A | #B -- justa.cue -- package x #A -- justb.cue -- package x #B -- x.cue -- package x #A: {a: string} #B: {b: int}cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_embed.txtar000066400000000000000000000013551474664451600247210ustar00rootroot00000000000000# Embedding at the file level should still close the package and validate # correctly against files from other packages without first merging these # files, thereby effectively embedding them and averting the closed check. # Issue #743 ! exec cue vet schema.cue foo.yaml cmp stderr expect-foo ! exec cue vet schema.cue stream.yaml cmp stderr expect-stream -- schema.cue -- package schema #Foo: { a: int b?: int } #Foo -- foo.yaml -- a: 1 c: 2 -- stream.yaml -- a: 1 d: 2 --- a: 1 e: 2 -- expect-foo -- c: field not allowed: ./foo.yaml:2:1 ./schema.cue:1:1 ./schema.cue:3:7 ./schema.cue:7:1 -- expect-stream -- d: field not allowed: ./schema.cue:1:1 ./schema.cue:3:7 ./schema.cue:7:1 ./stream.yaml:2:1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_expr.txtar000066400000000000000000000010731474664451600246200ustar00rootroot00000000000000! exec cue vet -d '#File' vet.cue data.yaml cmp stderr expect-stderr -- expect-stderr -- translations.hello.lang: incomplete value string: ./vet.cue:3:11 skip: field not allowed: ./data.yaml:20:1 ./vet.cue:1:8 -- vet.cue -- #File: { translations: [string]: { lang: string text: string } } -- data.yaml -- # translated messages translations: hello: lang: gsw text: Grüetzi --- translations: hello: text: Hoi --- translations: hello: lang: no text: Hallo --- translations: hello: lang: nl text: Hallo skip: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_file.txtar000066400000000000000000000017121474664451600245610ustar00rootroot00000000000000! exec cue vet ./vet.cue ./data.yaml cmp stderr expect-stderr ! exec cue vet . ./data.yaml cmp stderr expect-stderr2 -- expect-stderr -- translations.hello.lang: incomplete value string: ./vet.cue:3:31 translations.hello.lang: conflicting values false and string (mismatched types bool and string): ./data.yaml:13:11 ./vet.cue:3:25 ./vet.cue:3:31 -- expect-stderr2 -- translations.hello.lang: incomplete value string: ./vet.cue:3:31 translations.hello.lang: conflicting values false and string (mismatched types bool and string): ./data.yaml:13:11 ./vet.cue:3:25 ./vet.cue:3:31 -- vet.cue -- package foo translations: [string]: lang: string #File: { translations: {...} } -- data.yaml -- # translated messages translations: hello: lang: gsw text: Grüetzi --- translations: hello: text: Hoi --- translations: hello: lang: false text: Hallo --- translations: hello: lang: nl text: Hallo skip: true cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_issue1926.txtar000066400000000000000000000006431474664451600253160ustar00rootroot00000000000000# https://cuelang.org/issues/1926 exec cue export foo.cue dev.json exec cue vet foo.cue dev.json exec cue export foo.cue prd.json exec cue vet foo.cue prd.json -- foo.cue -- package foo _env: =~"(prd)-" #Foo #Foo: { env: "dev" | _env baz: bool | *false if env == "dev" { _defaults.dev } } _defaults: { "dev": { baz: true } } -- prd.json -- { "env": "prd-foo" } -- dev.json -- { "env": "dev" }cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_issue2704.txtar000066400000000000000000000011741474664451600253110ustar00rootroot00000000000000# https://cuelang.org/issues/2704 ! exec cue export schema.cue data.json cmp stderr evalv2-stderr.golden ! exec cue vet schema.cue data.json cmp stderr evalv2-stderr.golden # This issue is already fixed in the new evaluator. env CUE_EXPERIMENT=evalv3 exec cue export schema.cue data.json cmp stdout evalv3-stdout.golden exec cue vet schema.cue data.json ! stdout . -- evalv2-stderr.golden -- 1: invalid value "value" (out of bound =~"^[0-9]+$"): ./schema.cue:1:14 ./data.json:1:7 -- evalv3-stdout.golden -- [ "5", "value" ] -- schema.cue -- #schema: [...=~"^[0-9]+$" | string] #schema -- data.json -- ["5", "value"] cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_listmax.txtar000066400000000000000000000007301474664451600253220ustar00rootroot00000000000000# cuelang.org/issues/345 stdin foo.json exec cue vet x.cue json: - exec cue export foo.json x.cue cmp stdout out/x.json -- foo.json -- { "ports": [ 2, 5, 7, 2, 76, 98, 3 ], "newPort": 99 } -- x.cue -- import "list" ports: [... int] newPort: list.Max(ports) + 1 -- out/x.json -- { "ports": [ 2, 5, 7, 2, 76, 98, 3 ], "newPort": 99 } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_opt.txtar000066400000000000000000000002001474664451600244330ustar00rootroot00000000000000exec cue vet -c vet.cue cmp stdout expect-stdout -- expect-stdout -- -- vet.cue -- #Schema1: { a?: int } instance1: #Schema1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_path.txtar000066400000000000000000000012541474664451600245770ustar00rootroot00000000000000! exec cue vet -l 'strings.ToLower(kind)' -l name services.jsonl services.cue cmp stderr expect-stderr -- expect-stderr -- deployment.Booster.name: invalid value "Booster" (out of bound !~"^[A-Z]"): ./services.cue:1:29 ./services.jsonl:7:13 service."Supplement\nfoo".name: invalid value "Supplement\nfoo" (out of bound !~"^[A-Z]"): ./services.cue:2:26 ./services.jsonl:12:13 -- services.cue -- deployment: [string]: name: !~"^[A-Z]" service: [string]: name: !~"^[A-Z]" -- services.jsonl -- { "kind": "Service", "name": "booster" } { "kind": "Deployment", "name": "Booster", "replicas": 1 } { "kind": "Service", "name": "Supplement\nfoo" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_req.txtar000066400000000000000000000013641474664451600244340ustar00rootroot00000000000000! exec cue vet in.cue cmp stdout expect-stdout1 cmp stderr expect-stderr1 exec cue vet -c=false in.cue cmp stdout expect-stdout2 cmp stderr expect-stderr2 ! exec cue vet data.json in.cue cmp stdout expect-stdout3 cmp stderr expect-stderr3 ! exec cue vet data.yaml in.cue cmp stdout expect-stdout4 cmp stderr expect-stderr4 -- in.cue -- x!: string -- data.json -- {} -- data.yaml -- y: 1 -- expect-stdout1 -- -- expect-stderr1 -- some instances are incomplete; use the -c flag to show errors or suppress this message -- expect-stdout2 -- -- expect-stderr2 -- -- expect-stdout3 -- -- expect-stderr3 -- x: field is required but not present: ./in.cue:1:1 -- expect-stdout4 -- -- expect-stderr4 -- x: field is required but not present: ./in.cue:1:1 cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_trailing.txtar000066400000000000000000000025741474664451600254620ustar00rootroot00000000000000# Regression test for two vet issues relating trailing input, # https://cuelang.org/issue/2179 and https://cuelang.org/issue/2439. # First, sanity check that other commands spot the trailing invalid syntax. ! exec cue eval data-trailing-garbage.json stderr 'invalid JSON.*after top-level value' ! exec cue def data-trailing-garbage.json stderr 'invalid JSON.*after top-level value' ! exec cue export data-trailing-garbage.json stderr 'invalid JSON.*after top-level value' ! exec cue eval data-trailing-garbage.jsonl stderr 'invalid JSON.*looking for beginning of value' # Then, check that vet does too. ! exec cue vet schema.cue data-trailing-garbage.json stderr 'invalid JSON.*after top-level value' ! exec cue vet schema.cue data-trailing-garbage.jsonl stderr 'invalid JSON.*looking for beginning of value' # Check that even the last value is validated as well. ! exec cue vet schema.cue data-trailing-mismatch.json stderr 'invalid JSON.*after top-level value' ! exec cue vet schema.cue data-trailing-mismatch.jsonl stderr 'foo: conflicting values "789" and int' -- schema.cue -- foo: int -- data-trailing-garbage.json -- { "foo": 123 } hi there -- data-trailing-mismatch.json -- { "foo": 123 } { "foo": 456 } { "foo": "789" } -- data-trailing-garbage.jsonl -- { "foo": 123 } { "foo": 456 } hi there -- data-trailing-mismatch.jsonl -- { "foo": 123 } { "foo": 456 } { "foo": "789" } cue-lang-cue-db9cc73/cmd/cue/cmd/testdata/script/vet_yaml.txtar000066400000000000000000000021771474664451600246120ustar00rootroot00000000000000! exec cue vet ./yaml.cue cmp stderr expect-stderr -- expect-stderr -- phrases: invalid value "phrases:\n # A quote from Mark Twain.\n quote1:\n lang: en\n attribution: Mark Twain\n\n # A Norwegian proverb.\n proverb:\n lang: no\n text: Stemmen som sier at du ikke klarer det, lyver." (does not satisfy encoding/yaml.Validate): error in call to encoding/yaml.Validate: incomplete value !="": ./yaml.cue:19:10 ./yaml.cue:11:17 ./yaml.cue:21:10 -- yaml.cue -- import "encoding/yaml" // Phrases defines a schema for a valid phrase. #Phrases: { phrases: { [string]: #Phrase } #Phrase: { lang: #LanguageTag text: !="" attribution?: !="" // must be non-empty when specified } #LanguageTag: =~"^[a-zA-Z0-9-_]{2,}$" | false } // phrases is a YAML string with a field phrases that is a map of Phrase // objects. phrases: yaml.Validate(#Phrases) phrases: """ phrases: # A quote from Mark Twain. quote1: lang: en attribution: Mark Twain # A Norwegian proverb. proverb: lang: no text: Stemmen som sier at du ikke klarer det, lyver. """ cue-lang-cue-db9cc73/cmd/cue/cmd/trim.go000066400000000000000000000111231474664451600200620ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "errors" "fmt" "os" "github.com/spf13/cobra" "cuelang.org/go/cue/format" "cuelang.org/go/cue/load" "cuelang.org/go/internal/diff" "cuelang.org/go/tools/trim" ) // TODO: // - remove the limitations mentioned in the documentation // - implement verification post-processing as extra safety // newTrimCmd creates a trim command func newTrimCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "trim", Short: "remove superfluous fields", Long: `trim removes fields from structs that can be inferred from constraints A field, struct, or list is removed if it is implied by a constraint, such as from an optional field matching a required field, a list type value, a comprehension or any other implied content. It will modify the files in place. Limitations Removal is on a best effort basis. Some caveats: - Fields in implied content may refer to fields within the struct in which they are included, but are only resolved on a best-effort basis. - Disjunctions that contain structs in implied content cannot be used to remove fields. - There is currently no verification step: manual verification is required. Examples: $ cat < foo.cue light: [string]: { room: string brightnessOff: *0.0 | >=0 & <=100.0 brightnessOn: *100.0 | >=0 & <=100.0 } light: ceiling50: { room: "MasterBedroom" brightnessOff: 0.0 // this line brightnessOn: 100.0 // and this line will be removed } EOF $ cue trim foo.cue $ cat foo.cue light: [string]: { room: string brightnessOff: *0.0 | >=0 & <=100.0 brightnessOn: *100.0 | >=0 & <=100.0 } light: ceiling50: { room: "MasterBedroom" } It is guaranteed that the resulting files give the same output as before the removal. `, RunE: mkRunE(c, runTrim), } addOutFlags(cmd.Flags(), false) cmd.Flags().BoolP(string(flagDryRun), "n", false, "only run simulation") return cmd } func runTrim(cmd *Command, args []string) error { defCfg, err := defaultConfig() if err != nil { return err } binst := loadFromArgs(args, defCfg.loadCfg) if binst == nil { return nil } instances, err := buildInstances(cmd, binst, false) if err != nil { return err } dst := flagOutFile.String(cmd) if dst != "" && dst != "-" && !flagForce.Bool(cmd) { switch _, err := os.Stat(dst); { case os.IsNotExist(err): default: return fmt.Errorf("error writing %q: file already exists", dst) } } overlay := map[string]load.Source{} for i, inst := range binst { root := instances[i] err := trim.Files(inst.Files, root.Value(), &trim.Config{ Trace: flagTrace.Bool(cmd), }) if err != nil { return err } for _, f := range inst.Files { overlay[f.Filename] = load.FromFile(f) } } cfg := *defCfg.loadCfg cfg.Overlay = overlay tinsts, err := buildInstances(cmd, load.Instances(args, &cfg), false) if err != nil { return err } if len(tinsts) != len(binst) { return errors.New("unexpected number of new instances") } if !flagIgnore.Bool(cmd) { for i, p := range instances { k, script := diff.Final.Diff(p.Value(), tinsts[i].Value()) if k != diff.Identity { diff.Print(os.Stdout, script) fmt.Println("Aborting trim, output differs after trimming. This is a bug! Use -i to force trim.") fmt.Println("You can file a bug here: https://cuelang.org/issues/new?assignees=&labels=NeedsInvestigation&template=bug_report.md&title=") return ErrPrintedError } } } if flagDryRun.Bool(cmd) { return nil } for _, inst := range binst { for _, f := range inst.Files { filename := f.Filename opts := []format.Option{} if flagSimplify.Bool(cmd) { opts = append(opts, format.Simplify()) } b, err := format.Node(f, opts...) if err != nil { return fmt.Errorf("error formatting file: %v", err) } if dst == "-" { _, err := cmd.OutOrStdout().Write(b) if err != nil { return err } continue } else if dst != "" { filename = dst } err = os.WriteFile(filename, b, 0666) if err != nil { return err } } } return nil } cue-lang-cue-db9cc73/cmd/cue/cmd/version.go000066400000000000000000000053641474664451600206060ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "encoding/json" "errors" "fmt" "os" "runtime" "runtime/debug" "testing" "github.com/spf13/cobra" "cuelang.org/go/internal/cueversion" ) func newVersionCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "version", Short: "print CUE version", Long: ``, RunE: mkRunE(c, runVersion), } return cmd } // version can be set at build time to inject cmd/cue's version string, // particularly necessary when building a release locally. // See the top-level README.md for more details. var version string func runVersion(cmd *Command, args []string) error { w := cmd.OutOrStdout() // read in build info bi, ok := readBuildInfo() if !ok { // shouldn't happen return errors.New("unknown error reading build-info") } fmt.Fprintf(w, "cue version %s\n\n", cueModuleVersion()) fmt.Fprintf(w, "go version %s\n", runtime.Version()) bi.Settings = append(bi.Settings, debug.BuildSetting{ Key: "cue.lang.version", Value: cueversion.LanguageVersion(), }) for _, s := range bi.Settings { if s.Value == "" { // skip empty build settings continue } // The padding helps keep readability by aligning: // // veryverylong.key value // short.key some-other-value // // Empirically, 16 is enough; the longest key seen outside our own "cue.lang.version" // is "vcs.revision". fmt.Fprintf(w, "%16s %s\n", s.Key, s.Value) } return nil } // cueModuleVersion returns the version of the cuelang.org/go module as much // as can reasonably be determined. If no version can be determined, // it returns the empty string. func cueModuleVersion() string { if v := version; v != "" { // The global version variable has been configured via ldflags. return v } return cueversion.ModuleVersion() } func readBuildInfo() (*debug.BuildInfo, bool) { bi, ok := debug.ReadBuildInfo() if !ok || !testing.Testing() { return bi, ok } // test-based overrides if v := os.Getenv("CUE_VERSION_TEST_CFG"); v != "" { var extra []debug.BuildSetting if err := json.Unmarshal([]byte(v), &extra); err != nil { // It's only for tests, so panic is OK. panic(err) } bi.Settings = append(bi.Settings, extra...) } return bi, true } cue-lang-cue-db9cc73/cmd/cue/cmd/vet.go000066400000000000000000000105371474664451600177150ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "github.com/spf13/cobra" "golang.org/x/text/message" "cuelang.org/go/cue" "cuelang.org/go/cue/errors" ) const vetDoc = `vet validates CUE and other data files By default it will only validate if there are no errors. The -c validates that all regular fields are concrete. Checking non-CUE files Vet can also check non-CUE files. The following file formats are currently supported: Format Extensions JSON .json .jsonl .ndjson YAML .yaml .yml TOML .toml TEXT .txt (validate a single string value) To activate this mode, the non-cue files must be explicitly mentioned on the command line. There must also be at least one CUE file to hold the constraints. In this mode, each file will be verified against a CUE constraint. If the files contain multiple objects (such as using --- in YAML), they will all be verified individually. By default, each file is checked against the root of the loaded CUE files. The -d can be used to only verify files against the result of an expression evaluated within the CUE files. This can be useful if the CUE files contain a set of definitions to pick from. Examples: # Check files against a CUE file: cue vet foo.cue foo.yaml # Check files against a particular expression cue vet foo.cue lang/en.yaml lang/de.yaml -d '#Translation' More than one expression may be given using multiple -d flags. Each non-CUE file must match all expression values. ` func newVetCmd(c *Command) *cobra.Command { cmd := &cobra.Command{ Use: "vet", Short: "validate data", Long: vetDoc, RunE: mkRunE(c, doVet), } addOrphanFlags(cmd.Flags()) addInjectionFlags(cmd.Flags(), false, false) cmd.Flags().BoolP(string(flagConcrete), "c", false, "require the evaluation to be concrete") return cmd } // doVet validates instances. There are two modes: // - Only packages: vet all these packages // - Data files: compare each data instance against a single package. // // It is invalid to have data files with other than exactly one package. // // TODO: allow unrooted schema, such as JSON schema to compare against // other values. func doVet(cmd *Command, args []string) error { b, err := parseArgs(cmd, args, &config{ noMerge: true, }) if err != nil { return err } // Go into a special vet mode if the user explicitly specified non-cue // files on the command line. // TODO: unify these two modes. if len(b.orphaned) > 0 { return vetFiles(cmd, b) } shown := false iter := b.instances() defer iter.close() for iter.scan() { v := iter.value() // TODO: use ImportPath or some other sanitized path. concrete := true hasFlag := false if flag := cmd.Flag(string(flagConcrete)); flag != nil { hasFlag = flag.Changed if hasFlag { concrete = flagConcrete.Bool(cmd) } } opt := []cue.Option{ cue.Attributes(true), cue.Definitions(true), cue.Hidden(true), } w := cmd.Stderr() err := v.Validate(append(opt, cue.Concrete(concrete))...) if err != nil && !hasFlag { err = v.Validate(append(opt, cue.Concrete(false))...) if !shown && err == nil { shown = true p := message.NewPrinter(getLang()) _, _ = p.Fprintln(w, "some instances are incomplete; use the -c flag to show errors or suppress this message") } } printError(cmd, err) } if err := iter.err(); err != nil { return err } return nil } func vetFiles(cmd *Command, b *buildPlan) error { // Use -r type root, instead of -e if !b.encConfig.Schema.Exists() { return errors.New("data files specified without a schema") } iter := b.instances() defer iter.close() for iter.scan() { v := iter.value() // Always concrete when checking against concrete files. err := v.Validate(cue.Concrete(true)) printError(cmd, err) } if err := iter.err(); err != nil { return err } return nil } cue-lang-cue-db9cc73/cmd/cue/main.go000066400000000000000000000012651474664451600172760ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "os" "cuelang.org/go/cmd/cue/cmd" ) func main() { os.Exit(cmd.Main()) } cue-lang-cue-db9cc73/codereview.cfg000066400000000000000000000003111474664451600173100ustar00rootroot00000000000000# Code generated internal/ci/ci_tool.cue; DO NOT EDIT. gerrit: https://review.gerrithub.io/a/cue-lang/cue github: https://github.com/cue-lang/cue cue-unity: https://github.com/cue-unity/unity-private cue-lang-cue-db9cc73/cue.mod/000077500000000000000000000000001474664451600160325ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue.mod/module.cue000066400000000000000000000002511474664451600200130ustar00rootroot00000000000000module: "cuelang.org/go" language: { version: "v0.8.0" } deps: { "github.com/cue-tmp/jsonschema-pub/exp1/githubactions@v0": { v: "v0.4.0" default: true } } cue-lang-cue-db9cc73/cue/000077500000000000000000000000001474664451600152545ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/ast/000077500000000000000000000000001474664451600160435ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/ast/ast.go000066400000000000000000000672001474664451600171660ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package ast declares the types used to represent syntax trees for CUE // packages. package ast import ( "fmt" "strings" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/token" ) // ---------------------------------------------------------------------------- // Interfaces // // There are three main classes of nodes: expressions, clauses, and declaration // nodes. The node names usually match the corresponding CUE spec production // names to which they correspond. The node fields correspond to the individual // parts of the respective productions. // // All nodes contain position information marking the beginning of the // corresponding source text segment; it is accessible via the Pos accessor // method. Nodes may contain additional position info for language constructs // where comments may be found between parts of the construct (typically any // larger, parenthesized subpart). That position information is needed to // properly position comments when printing the construct. // A Node represents any node in the abstract syntax tree. type Node interface { Pos() token.Pos // position of first character belonging to the node End() token.Pos // position of first character immediately after the node // pos reports the pointer to the position of first character belonging to // the node or nil if there is no such position. pos() *token.Pos // Deprecated: use [Comments] Comments() []*CommentGroup // Deprecated: use [AddComment] AddComment(*CommentGroup) commentInfo() *comments } // Name describes the type of n. func Name(n Node) string { s := fmt.Sprintf("%T", n) return strings.ToLower(s[strings.Index(s, "ast.")+4:]) } func getPos(n Node) token.Pos { p := n.pos() if p == nil { return token.NoPos } return *p } // SetPos sets a node to the given position, if possible. func SetPos(n Node, p token.Pos) { ptr := n.pos() if ptr == nil { return } *ptr = p } // SetRelPos sets the relative position of a node without modifying its // file position. Setting it to token.NoRelPos allows a node to adopt default // formatting. func SetRelPos(n Node, p token.RelPos) { ptr := n.pos() if ptr == nil { return } pos := *ptr *ptr = pos.WithRel(p) } // An Expr is implemented by all expression nodes. type Expr interface { Node declNode() // An expression can be used as a declaration. exprNode() } type expr struct{ decl } func (expr) exprNode() {} // A Decl node is implemented by all declarations. type Decl interface { Node declNode() } type decl struct{} func (decl) declNode() {} // A Label is any production that can be used as an LHS label. type Label interface { Node labelNode() } type label struct{} func (l label) labelNode() {} // Clause nodes are part of comprehensions. type Clause interface { Node clauseNode() } type clause struct{} func (clause) clauseNode() {} // Comments type comments struct { groups *[]*CommentGroup } func (c *comments) commentInfo() *comments { return c } func (c *comments) Comments() []*CommentGroup { if c.groups == nil { return []*CommentGroup{} } return *c.groups } // // AddComment adds the given comments to the fields. // // If line is true the comment is inserted at the preceding token. func (c *comments) AddComment(cg *CommentGroup) { if cg == nil { return } if c.groups == nil { a := []*CommentGroup{cg} c.groups = &a return } *c.groups = append(*c.groups, cg) a := *c.groups for i := len(a) - 2; i >= 0 && a[i].Position > cg.Position; i-- { a[i], a[i+1] = a[i+1], a[i] } } func (c *comments) SetComments(cgs []*CommentGroup) { if c.groups == nil { a := cgs c.groups = &a return } *c.groups = cgs } // A Comment node represents a single //-style comment. type Comment struct { Slash token.Pos // position of "/" starting the comment Text string // comment text excluding '\n' } func (c *Comment) Comments() []*CommentGroup { return nil } func (c *Comment) AddComment(*CommentGroup) {} func (c *Comment) commentInfo() *comments { return nil } func (c *Comment) Pos() token.Pos { return c.Slash } func (c *Comment) pos() *token.Pos { return &c.Slash } func (c *Comment) End() token.Pos { return c.Slash.Add(len(c.Text)) } // A CommentGroup represents a sequence of comments // with no other tokens and no empty lines between. type CommentGroup struct { // TODO: remove and use the token position of the first comment. Doc bool Line bool // true if it is on the same line as the node's end pos. // Position indicates where a comment should be attached if a node has // multiple tokens. 0 means before the first token, 1 means before the // second, etc. For instance, for a field, the positions are: // <0> Label <1> ":" <2> Expr <3> "," <4> Position int8 List []*Comment // len(List) > 0 decl } func (g *CommentGroup) Pos() token.Pos { return getPos(g) } func (g *CommentGroup) pos() *token.Pos { return g.List[0].pos() } func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() } func (g *CommentGroup) Comments() []*CommentGroup { return nil } func (g *CommentGroup) AddComment(*CommentGroup) {} func (g *CommentGroup) commentInfo() *comments { return nil } func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' } func stripTrailingWhitespace(s string) string { i := len(s) for i > 0 && isWhitespace(s[i-1]) { i-- } return s[0:i] } // Text returns the text of the comment. // Comment markers ("//"), the first space of a line comment, and // leading and trailing empty lines are removed. Multiple empty lines are // reduced to one, and trailing space on lines is trimmed. Unless the result // is empty, it is newline-terminated. func (g *CommentGroup) Text() string { if g == nil { return "" } comments := make([]string, len(g.List)) for i, c := range g.List { comments[i] = c.Text } lines := make([]string, 0, 10) // most comments are less than 10 lines for _, c := range comments { // Remove comment markers. // The parser has given us exactly the comment text. c = c[2:] // strip first space - required for Example tests if len(c) > 0 && c[0] == ' ' { c = c[1:] } // Split on newlines. cl := strings.Split(c, "\n") // Walk lines, stripping trailing white space and adding to list. for _, l := range cl { lines = append(lines, stripTrailingWhitespace(l)) } } // Remove leading blank lines; convert runs of // interior blank lines to a single blank line. n := 0 for _, line := range lines { if line != "" || n > 0 && lines[n-1] != "" { lines[n] = line n++ } } lines = lines[0:n] // Add final "" entry to get trailing newline from Join. if n > 0 && lines[n-1] != "" { lines = append(lines, "") } return strings.Join(lines, "\n") } // An Attribute provides meta data about a field. type Attribute struct { At token.Pos Text string // must be a valid attribute format. comments decl } func (a *Attribute) Pos() token.Pos { return a.At } func (a *Attribute) pos() *token.Pos { return &a.At } func (a *Attribute) End() token.Pos { return a.At.Add(len(a.Text)) } func (a *Attribute) Split() (key, body string) { s := a.Text p := strings.IndexByte(s, '(') if p < 0 || !strings.HasPrefix(s, "@") || !strings.HasSuffix(s, ")") { return "", "" } return a.Text[1:p], a.Text[p+1 : len(s)-1] } // A Field represents a field declaration in a struct. type Field struct { Label Label // must have at least one element. Optional token.Pos // Deprecated Constraint token.Token // token.ILLEGAL, token.OPTION, or token.NOT // No TokenPos: Value must be an StructLit with one field. TokenPos token.Pos Token token.Token // Deprecated: always token.COLON Value Expr // the value associated with this field. Attrs []*Attribute comments decl } func (d *Field) Pos() token.Pos { return d.Label.Pos() } func (d *Field) pos() *token.Pos { return d.Label.pos() } func (d *Field) End() token.Pos { if len(d.Attrs) > 0 { return d.Attrs[len(d.Attrs)-1].End() } return d.Value.End() } // TODO: make Alias a type of Field. This is possible now we have different // separator types. // An Alias binds another field to the alias name in the current struct. type Alias struct { Ident *Ident // field name, always an Ident Equal token.Pos // position of "=" Expr Expr // An Ident or SelectorExpr comments clause decl expr label } func (a *Alias) Pos() token.Pos { return a.Ident.Pos() } func (a *Alias) pos() *token.Pos { return a.Ident.pos() } func (a *Alias) End() token.Pos { return a.Expr.End() } // A Comprehension node represents a comprehension declaration. type Comprehension struct { Clauses []Clause // There must be at least one clause. Value Expr // Must be a struct TODO: change to Struct comments decl expr // TODO: only allow Comprehension in "Embedding" productions. } func (x *Comprehension) Pos() token.Pos { return getPos(x) } func (x *Comprehension) pos() *token.Pos { return x.Clauses[0].pos() } func (x *Comprehension) End() token.Pos { return x.Value.End() } // ---------------------------------------------------------------------------- // Expressions and types // // An expression is represented by a tree consisting of one // or more of the following concrete expression nodes. // A BadExpr node is a placeholder for expressions containing // syntax errors for which no correct expression nodes can be // created. This is different from an ErrorExpr which represents // an explicitly marked error in the source. type BadExpr struct { From, To token.Pos // position range of bad expression comments expr } // A BottomLit indicates an error. type BottomLit struct { Bottom token.Pos comments expr } // An Ident node represents a left-hand side identifier, // including the underscore "_" identifier to represent top. type Ident struct { NamePos token.Pos // identifier position // This LHS path element may be an identifier. Possible forms: // foo: a normal identifier // "foo": JSON compatible Name string Scope Node // scope in which node was found or nil if referring directly Node Node comments label expr } // A BasicLit node represents a literal of basic type. type BasicLit struct { ValuePos token.Pos // literal position Kind token.Token // INT, FLOAT, DURATION, or STRING Value string // literal string; e.g. 42, 0x7f, 3.14, 1_234_567, 1e-9, 2.4i, 'a', '\x7f', "foo", or '\m\n\o' comments expr label } // TODO: introduce and use NewLabel and NewBytes and perhaps NewText (in the // later case NewString would return a string or bytes type) to distinguish from // NewString. Consider how to pass indentation information. // NewString creates a new BasicLit with a string value without position. // It quotes the given string. // Useful for ASTs generated by code other than the CUE parser. func NewString(str string) *BasicLit { str = literal.String.Quote(str) return &BasicLit{Kind: token.STRING, ValuePos: token.NoPos, Value: str} } // NewNull creates a new BasicLit configured to be a null value. // Useful for ASTs generated by code other than the CUE parser. func NewNull() *BasicLit { return &BasicLit{Kind: token.NULL, Value: "null"} } // NewLit creates a new BasicLit with from a token type and string without // position. // Useful for ASTs generated by code other than the CUE parser. func NewLit(tok token.Token, s string) *BasicLit { return &BasicLit{Kind: tok, Value: s} } // NewBool creates a new BasicLit with a bool value without position. // Useful for ASTs generated by code other than the CUE parser. func NewBool(b bool) *BasicLit { x := &BasicLit{} if b { x.Kind = token.TRUE x.Value = "true" } else { x.Kind = token.FALSE x.Value = "false" } return x } // TODO: // - use CUE-specific quoting (hoist functionality in export) // - NewBytes // A Interpolation node represents a string or bytes interpolation. type Interpolation struct { Elts []Expr // interleaving of strings and expressions. comments expr label } // A Func node represents a function type. // // This is an experimental type and the contents will change without notice. type Func struct { Func token.Pos // position of "func" Args []Expr // list of elements; or nil Ret Expr // return type, must not be nil comments expr } // A StructLit node represents a literal struct. type StructLit struct { Lbrace token.Pos // position of "{" Elts []Decl // list of elements; or nil Rbrace token.Pos // position of "}" comments expr } // NewStruct creates a struct from the given fields. // // A field is either a *Field, an *Ellipsis, *LetClause, a *CommentGroup, or a // Label, optionally followed by a token.OPTION or token.NOT to indicate the // field is optional or required, followed by an expression for the field value. // // It will panic if a values not matching these patterns are given. Useful for // ASTs generated by code other than the CUE parser. func NewStruct(fields ...interface{}) *StructLit { s := &StructLit{ // Set default positions so that comment attachment is as expected. Lbrace: token.NoSpace.Pos(), } for i := 0; i < len(fields); i++ { var ( label Label optional = token.NoPos constraint = token.ILLEGAL expr Expr ) switch x := fields[i].(type) { case *Field: s.Elts = append(s.Elts, x) continue case *CommentGroup: s.Elts = append(s.Elts, x) continue case *Ellipsis: s.Elts = append(s.Elts, x) continue case *LetClause: s.Elts = append(s.Elts, x) continue case *embedding: s.Elts = append(s.Elts, (*EmbedDecl)(x)) continue case Label: label = x case string: label = NewString(x) default: panic(fmt.Sprintf("unsupported label type %T", x)) } inner: for i++; i < len(fields); i++ { switch x := (fields[i]).(type) { case Expr: expr = x break inner case token.Token: switch x { case token.OPTION: constraint = x optional = token.Blank.Pos() case token.NOT: constraint = x case token.COLON, token.ILLEGAL: default: panic(fmt.Sprintf("invalid token %s", x)) } default: panic(fmt.Sprintf("unsupported expression type %T", x)) } } if expr == nil { panic("label not matched with expression") } s.Elts = append(s.Elts, &Field{ Label: label, Optional: optional, Constraint: constraint, Value: expr, }) } return s } // Embed can be used in conjunction with NewStruct to embed values. func Embed(x Expr) *embedding { return (*embedding)(&EmbedDecl{Expr: x}) } type embedding EmbedDecl // A ListLit node represents a literal list. type ListLit struct { Lbrack token.Pos // position of "[" // TODO: change to embedding or similar. Elts []Expr // list of composite elements; or nil Rbrack token.Pos // position of "]" comments expr label } // NewList creates a list of Expressions. // Useful for ASTs generated by code other than the CUE parser. func NewList(exprs ...Expr) *ListLit { return &ListLit{Elts: exprs} } type Ellipsis struct { Ellipsis token.Pos // open list if set Type Expr // type for the remaining elements comments decl expr } // A ForClause node represents a for clause in a comprehension. type ForClause struct { For token.Pos Key *Ident // allow pattern matching? // TODO: change to Comma Colon token.Pos Value *Ident // allow pattern matching? In token.Pos Source Expr comments clause } // A IfClause node represents an if guard clause in a comprehension. type IfClause struct { If token.Pos Condition Expr comments clause } // A LetClause node represents a let clause in a comprehension. type LetClause struct { Let token.Pos Ident *Ident Equal token.Pos Expr Expr comments clause decl } // A ParenExpr node represents a parenthesized expression. type ParenExpr struct { Lparen token.Pos // position of "(" X Expr // parenthesized expression Rparen token.Pos // position of ")" comments expr label } // A SelectorExpr node represents an expression followed by a selector. type SelectorExpr struct { X Expr // expression Sel Label // field selector comments expr } // NewSel creates a sequence of selectors. // Useful for ASTs generated by code other than the CUE parser. func NewSel(x Expr, sel ...string) Expr { for _, s := range sel { x = &SelectorExpr{X: x, Sel: NewIdent(s)} } return x } // An IndexExpr node represents an expression followed by an index. type IndexExpr struct { X Expr // expression Lbrack token.Pos // position of "[" Index Expr // index expression Rbrack token.Pos // position of "]" comments expr } // An SliceExpr node represents an expression followed by slice indices. type SliceExpr struct { X Expr // expression Lbrack token.Pos // position of "[" Low Expr // begin of slice range; or nil High Expr // end of slice range; or nil Rbrack token.Pos // position of "]" comments expr } // A CallExpr node represents an expression followed by an argument list. type CallExpr struct { Fun Expr // function expression Lparen token.Pos // position of "(" Args []Expr // function arguments; or nil Rparen token.Pos // position of ")" comments expr } // NewCall creates a new CallExpr. // Useful for ASTs generated by code other than the CUE parser. func NewCall(fun Expr, args ...Expr) *CallExpr { return &CallExpr{Fun: fun, Args: args} } // A UnaryExpr node represents a unary expression. type UnaryExpr struct { OpPos token.Pos // position of Op Op token.Token // operator X Expr // operand comments expr } // A BinaryExpr node represents a binary expression. type BinaryExpr struct { X Expr // left operand OpPos token.Pos // position of Op Op token.Token // operator Y Expr // right operand comments expr } // NewBinExpr creates for list of expressions of length 2 or greater a chained // binary expression of the form (((x1 op x2) op x3) ...). For lists of length // 1 it returns the expression itself. It panics for empty lists. // Useful for ASTs generated by code other than the CUE parser. func NewBinExpr(op token.Token, operands ...Expr) Expr { if len(operands) == 0 { return nil } expr := operands[0] for _, e := range operands[1:] { expr = &BinaryExpr{X: expr, Op: op, Y: e} } return expr } // token.Pos and End implementations for expression/type nodes. func (x *BadExpr) Pos() token.Pos { return x.From } func (x *BadExpr) pos() *token.Pos { return &x.From } func (x *Ident) Pos() token.Pos { return x.NamePos } func (x *Ident) pos() *token.Pos { return &x.NamePos } func (x *BasicLit) Pos() token.Pos { return x.ValuePos } func (x *BasicLit) pos() *token.Pos { return &x.ValuePos } func (x *Interpolation) Pos() token.Pos { return x.Elts[0].Pos() } func (x *Interpolation) pos() *token.Pos { return x.Elts[0].pos() } func (x *Func) Pos() token.Pos { return x.Func } func (x *Func) pos() *token.Pos { return &x.Func } func (x *StructLit) Pos() token.Pos { return getPos(x) } func (x *StructLit) pos() *token.Pos { if x.Lbrace == token.NoPos && len(x.Elts) > 0 { return x.Elts[0].pos() } return &x.Lbrace } func (x *ListLit) Pos() token.Pos { return x.Lbrack } func (x *ListLit) pos() *token.Pos { return &x.Lbrack } func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis } func (x *Ellipsis) pos() *token.Pos { return &x.Ellipsis } func (x *LetClause) Pos() token.Pos { return x.Let } func (x *LetClause) pos() *token.Pos { return &x.Let } func (x *ForClause) Pos() token.Pos { return x.For } func (x *ForClause) pos() *token.Pos { return &x.For } func (x *IfClause) Pos() token.Pos { return x.If } func (x *IfClause) pos() *token.Pos { return &x.If } func (x *ParenExpr) Pos() token.Pos { return x.Lparen } func (x *ParenExpr) pos() *token.Pos { return &x.Lparen } func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() } func (x *SelectorExpr) pos() *token.Pos { return x.X.pos() } func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() } func (x *IndexExpr) pos() *token.Pos { return x.X.pos() } func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() } func (x *SliceExpr) pos() *token.Pos { return x.X.pos() } func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() } func (x *CallExpr) pos() *token.Pos { return x.Fun.pos() } func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } func (x *UnaryExpr) pos() *token.Pos { return &x.OpPos } func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } func (x *BinaryExpr) pos() *token.Pos { return x.X.pos() } func (x *BottomLit) Pos() token.Pos { return x.Bottom } func (x *BottomLit) pos() *token.Pos { return &x.Bottom } func (x *BadExpr) End() token.Pos { return x.To } func (x *Ident) End() token.Pos { return x.NamePos.Add(len(x.Name)) } func (x *BasicLit) End() token.Pos { return x.ValuePos.Add(len(x.Value)) } func (x *Interpolation) End() token.Pos { return x.Elts[len(x.Elts)-1].Pos() } func (x *Func) End() token.Pos { return x.Ret.End() } func (x *StructLit) End() token.Pos { if x.Rbrace == token.NoPos && len(x.Elts) > 0 { return x.Elts[len(x.Elts)-1].End() } return x.Rbrace.Add(1) } func (x *ListLit) End() token.Pos { return x.Rbrack.Add(1) } func (x *Ellipsis) End() token.Pos { if x.Type != nil { return x.Type.End() } return x.Ellipsis.Add(3) // len("...") } func (x *LetClause) End() token.Pos { return x.Expr.End() } func (x *ForClause) End() token.Pos { return x.Source.End() } func (x *IfClause) End() token.Pos { return x.Condition.End() } func (x *ParenExpr) End() token.Pos { return x.Rparen.Add(1) } func (x *SelectorExpr) End() token.Pos { return x.Sel.End() } func (x *IndexExpr) End() token.Pos { return x.Rbrack.Add(1) } func (x *SliceExpr) End() token.Pos { return x.Rbrack.Add(1) } func (x *CallExpr) End() token.Pos { return x.Rparen.Add(1) } func (x *UnaryExpr) End() token.Pos { return x.X.End() } func (x *BinaryExpr) End() token.Pos { return x.Y.End() } func (x *BottomLit) End() token.Pos { return x.Bottom.Add(1) } // ---------------------------------------------------------------------------- // Convenience functions for Idents // NewIdent creates a new Ident without position. // Useful for ASTs generated by code other than the CUE parser. func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil, nil, comments{}, label{}, expr{}} } func (id *Ident) String() string { if id != nil { return id.Name } return "" } // ---------------------------------------------------------------------------- // Declarations // An ImportSpec node represents a single package import. type ImportSpec struct { Name *Ident // local package name (including "."); or nil Path *BasicLit // import path EndPos token.Pos // end of spec (overrides Path.Pos if nonzero) comments } func (*ImportSpec) specNode() {} func NewImport(name *Ident, importPath string) *ImportSpec { importPath = literal.String.Quote(importPath) path := &BasicLit{Kind: token.STRING, Value: importPath} return &ImportSpec{Name: name, Path: path} } // Pos and End implementations for spec nodes. func (s *ImportSpec) Pos() token.Pos { return getPos(s) } func (s *ImportSpec) pos() *token.Pos { if s.Name != nil { return s.Name.pos() } return s.Path.pos() } // func (s *AliasSpec) Pos() token.Pos { return s.Name.Pos() } // func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() } // func (s *TypeSpec) Pos() token.Pos { return s.Name.Pos() } func (s *ImportSpec) End() token.Pos { if s.EndPos != token.NoPos { return s.EndPos } return s.Path.End() } // A BadDecl node is a placeholder for declarations containing // syntax errors for which no correct declaration nodes can be // created. type BadDecl struct { From, To token.Pos // position range of bad declaration comments decl } // A ImportDecl node represents a series of import declarations. A valid // Lparen position (Lparen.Line > 0) indicates a parenthesized declaration. type ImportDecl struct { Import token.Pos Lparen token.Pos // position of '(', if any Specs []*ImportSpec Rparen token.Pos // position of ')', if any comments decl } type Spec interface { Node specNode() } // An EmbedDecl node represents a single expression used as a declaration. // The expressions in this declaration is what will be emitted as // configuration output. // // An EmbedDecl may only appear at the top level. type EmbedDecl struct { Expr Expr comments decl } // Pos and End implementations for declaration nodes. func (d *BadDecl) Pos() token.Pos { return d.From } func (d *BadDecl) pos() *token.Pos { return &d.From } func (d *ImportDecl) Pos() token.Pos { return d.Import } func (d *ImportDecl) pos() *token.Pos { return &d.Import } func (d *EmbedDecl) Pos() token.Pos { return d.Expr.Pos() } func (d *EmbedDecl) pos() *token.Pos { return d.Expr.pos() } func (d *BadDecl) End() token.Pos { return d.To } func (d *ImportDecl) End() token.Pos { if d.Rparen.IsValid() { return d.Rparen.Add(1) } if len(d.Specs) == 0 { return token.NoPos } return d.Specs[0].End() } func (d *EmbedDecl) End() token.Pos { return d.Expr.End() } // ---------------------------------------------------------------------------- // Files and packages // A File node represents a CUE source file. type File struct { Filename string Decls []Decl // top-level declarations; or nil Imports []*ImportSpec // imports in this file Unresolved []*Ident // unresolved identifiers in this file comments } // Preamble returns the declarations of the preamble. func (f *File) Preamble() []Decl { p := 0 outer: for i, d := range f.Decls { switch d.(type) { default: break outer case *Package: p = i + 1 case *CommentGroup: case *Attribute: case *ImportDecl: p = i + 1 } } return f.Decls[:p] } func (f *File) VisitImports(fn func(d *ImportDecl)) { for _, d := range f.Decls { switch x := d.(type) { case *CommentGroup: case *Package: case *Attribute: case *ImportDecl: fn(x) default: return } } } // PackageName returns the package name associated with this file or "" if no // package is associated. func (f *File) PackageName() string { for _, d := range f.Decls { switch x := d.(type) { case *Package: if x.Name.Name == "_" { return "" } return x.Name.Name case *CommentGroup, *Attribute: default: return "" } } return "" } func (f *File) Pos() token.Pos { if len(f.Decls) > 0 { return f.Decls[0].Pos() } if f.Filename != "" { // TODO. Do something more principled and efficient. return token.NewFile(f.Filename, -1, 1).Pos(0, 0) } return token.NoPos } func (f *File) pos() *token.Pos { if len(f.Decls) > 0 { return f.Decls[0].pos() } if f.Filename != "" { return nil } return nil } func (f *File) End() token.Pos { if n := len(f.Decls); n > 0 { return f.Decls[n-1].End() } return token.NoPos } // A Package represents a package clause. type Package struct { PackagePos token.Pos // position of "package" pseudo-keyword Name *Ident // package name comments decl } func (p *Package) Pos() token.Pos { return getPos(p) } func (p *Package) pos() *token.Pos { if p.PackagePos != token.NoPos { return &p.PackagePos } if p.Name != nil { return p.Name.pos() } return nil } func (p *Package) End() token.Pos { if p.Name != nil { return p.Name.End() } return token.NoPos } cue-lang-cue-db9cc73/cue/ast/ast_test.go000066400000000000000000000061241474664451600202230ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ast_test import ( "testing" "github.com/go-quicktest/qt" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/format" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/cuetest" "cuelang.org/go/internal/tdtest" ) func TestCommentText(t *testing.T) { testCases := []struct { list []string text string }{ {[]string{"//"}, ""}, {[]string{"// "}, ""}, {[]string{"//", "//", "// "}, ""}, {[]string{"// foo "}, "foo\n"}, {[]string{"//", "//", "// foo"}, "foo\n"}, {[]string{"// foo bar "}, "foo bar\n"}, {[]string{"// foo", "// bar"}, "foo\nbar\n"}, {[]string{"// foo", "//", "//", "//", "// bar"}, "foo\n\nbar\n"}, {[]string{"//", "//", "//", "// foo", "//", "//", "//"}, "foo\n"}, } for i, c := range testCases { list := make([]*ast.Comment, len(c.list)) for i, s := range c.list { list[i] = &ast.Comment{Text: s} } text := (&ast.CommentGroup{List: list}).Text() if text != c.text { t.Errorf("case %d: got %q; expected %q", i, text, c.text) } } } func TestPackageName(t *testing.T) { testCases := []struct { input string pkg string }{{ input: ` package foo `, pkg: "foo", }, { input: ` a: 2 `, }, { input: ` // Comment // Package foo ... package foo `, pkg: "foo", }} for _, tc := range testCases { t.Run("", func(t *testing.T) { f, err := parser.ParseFile("test", tc.input) if err != nil { t.Fatal(err) } qt.Assert(t, qt.Equals(f.PackageName(), tc.pkg)) }) } } func TestNewStruct(t *testing.T) { type testCase struct { input []any want string } testCases := []testCase{{ input: []any{ internal.NewComment(true, "foo"), &ast.Ellipsis{}, }, want: `{ // foo ... }`}, { input: []any{ &ast.LetClause{Ident: ast.NewIdent("foo"), Expr: ast.NewIdent("bar")}, ast.Label(ast.NewString("bar")), ast.NewString("baz"), &ast.Field{ Label: ast.NewString("a"), Value: ast.NewString("b"), }, }, want: `{ let foo = bar "bar": "baz" "a": "b" }`}, { input: []any{ ast.NewIdent("opt"), token.OPTION, ast.NewString("foo"), ast.NewIdent("req"), token.NOT, ast.NewString("bar"), }, want: `{ opt?: "foo" req!: "bar" }`}, { input: []any{ast.Embed(ast.NewBool(true))}, want: `{ true }`}} // TODO(tdtest): use cuetest.Run when supported. tdtest.Run(t, testCases, func(t *cuetest.T, tc *testCase) { s := ast.NewStruct(tc.input...) b, err := format.Node(s) if err != nil { t.Fatal(err) } t.Equal(string(b), tc.want) }) } cue-lang-cue-db9cc73/cue/ast/astutil/000077500000000000000000000000001474664451600175305ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/ast/astutil/apply.go000066400000000000000000000301521474664451600212050ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil import ( "encoding/hex" "fmt" "hash/fnv" "reflect" "cuelang.org/go/cue/ast" ) // A Cursor describes a node encountered during Apply. // Information about the node and its parent is available // from the Node, Parent, and Index methods. // // The methods Replace, Delete, InsertBefore, and InsertAfter // can be used to change the AST without disrupting Apply. // Delete, InsertBefore, and InsertAfter are only defined for modifying // a StructLit and will panic in any other context. type Cursor interface { // Node returns the current Node. Node() ast.Node // Parent returns the parent of the current Node. Parent() Cursor // Index reports the index >= 0 of the current Node in the slice of Nodes // that contains it, or a value < 0 if the current Node is not part of a // list. Index() int // Import reports an opaque identifier that refers to the given package. It // may only be called if the input to apply was an ast.File. If the import // does not exist, it will be added. // // Deprecated: use [ast.NewImport] as an [ast.Ident.Node], and then // [Sanitize]. Import(path string) *ast.Ident // Replace replaces the current Node with n. // The replacement node is not walked by Apply. Comments of the old node // are copied to the new node if it has not yet an comments associated // with it. Replace(n ast.Node) // Delete deletes the current Node from its containing struct. // If the current Node is not part of a struct, Delete panics. Delete() // InsertAfter inserts n after the current Node in its containing struct. // If the current Node is not part of a struct, InsertAfter panics. // Unless n is wrapped by ApplyRecursively, Apply does not walk n. InsertAfter(n ast.Node) // InsertBefore inserts n before the current Node in its containing struct. // If the current Node is not part of a struct, InsertBefore panics. // Unless n is wrapped by ApplyRecursively, Apply does not walk n. InsertBefore(n ast.Node) self() *cursor } // ApplyRecursively indicates that a node inserted with InsertBefore, // or InsertAfter should be processed recursively. func ApplyRecursively(n ast.Node) ast.Node { return recursive{n} } type recursive struct { ast.Node } type info struct { f *ast.File current *declsCursor importPatch []*ast.Ident } type cursor struct { file *info parent Cursor node ast.Node typ interface{} // the type of the node index int // position of any of the sub types. replaced bool } func newCursor(parent Cursor, n ast.Node, typ interface{}) *cursor { return &cursor{ parent: parent, typ: typ, node: n, index: -1, } } func fileInfo(c Cursor) (info *info) { for ; c != nil; c = c.Parent() { if i := c.self().file; i != nil { return i } } return nil } func (c *cursor) self() *cursor { return c } func (c *cursor) Parent() Cursor { return c.parent } func (c *cursor) Index() int { return c.index } func (c *cursor) Node() ast.Node { return c.node } // Deprecated: use [ast.NewImport] as an [ast.Ident.Node], and then // [Sanitize]. func (c *cursor) Import(importPath string) *ast.Ident { info := fileInfo(c) if info == nil { return nil } name := ImportPathName(importPath) // TODO: come up with something much better. // For instance, hoist the uniquer form cue/export.go to // here and make export.go use this. hash := fnv.New32() name += hex.EncodeToString(hash.Sum([]byte(importPath)))[:6] spec := insertImport(&info.current.decls, &ast.ImportSpec{ Name: ast.NewIdent(name), Path: ast.NewString(importPath), }) ident := &ast.Ident{Node: spec} // Name is set later. info.importPatch = append(info.importPatch, ident) ident.Name = name return ident } func (c *cursor) Replace(n ast.Node) { // panic if the value cannot convert to the original type. reflect.ValueOf(n).Convert(reflect.TypeOf(c.typ).Elem()) if ast.Comments(n) != nil { CopyComments(n, c.node) } if r, ok := n.(recursive); ok { n = r.Node } else { c.replaced = true } c.node = n } func (c *cursor) InsertAfter(n ast.Node) { panic("unsupported") } func (c *cursor) InsertBefore(n ast.Node) { panic("unsupported") } func (c *cursor) Delete() { panic("unsupported") } // Apply traverses a syntax tree recursively, starting with root, // and calling pre and post for each node as described below. // Apply returns the syntax tree, possibly modified. // // If pre is not nil, it is called for each node before the node's // children are traversed (pre-order). If pre returns false, no // children are traversed, and post is not called for that node. // // If post is not nil, and a prior call of pre didn't return false, // post is called for each node after its children are traversed // (post-order). If post returns false, traversal is terminated and // Apply returns immediately. // // Only fields that refer to AST nodes are considered children; // i.e., token.Pos, Scopes, Objects, and fields of basic types // (strings, etc.) are ignored. // // Children are traversed in the order in which they appear in the // respective node's struct definition. func Apply(node ast.Node, before, after func(Cursor) bool) ast.Node { apply(&applier{before: before, after: after}, nil, &node) return node } // A applyVisitor's before method is invoked for each node encountered by Walk. // If the result applyVisitor w is true, Walk visits each of the children // of node with the applyVisitor w, followed by a call of w.After. type applyVisitor interface { Before(Cursor) applyVisitor After(Cursor) bool } // Helper functions for common node lists. They may be empty. type declsCursor struct { *cursor decls, after, process []ast.Decl delete bool } func (c *declsCursor) InsertAfter(n ast.Node) { if r, ok := n.(recursive); ok { n = r.Node c.process = append(c.process, n.(ast.Decl)) } c.after = append(c.after, n.(ast.Decl)) } func (c *declsCursor) InsertBefore(n ast.Node) { if r, ok := n.(recursive); ok { n = r.Node c.process = append(c.process, n.(ast.Decl)) } c.decls = append(c.decls, n.(ast.Decl)) } func (c *declsCursor) Delete() { c.delete = true } func applyDeclList(v applyVisitor, parent Cursor, list []ast.Decl) []ast.Decl { c := &declsCursor{ cursor: newCursor(parent, nil, nil), decls: make([]ast.Decl, 0, len(list)), } if file, ok := parent.Node().(*ast.File); ok { c.cursor.file = &info{f: file, current: c} } for i, x := range list { c.node = x c.typ = &list[i] applyCursor(v, c) if !c.delete { c.decls = append(c.decls, c.node.(ast.Decl)) } c.delete = false for i := 0; i < len(c.process); i++ { x := c.process[i] c.node = x c.typ = &c.process[i] applyCursor(v, c) if c.delete { panic("cannot delete a node that was added with InsertBefore or InsertAfter") } } c.decls = append(c.decls, c.after...) c.after = c.after[:0] c.process = c.process[:0] } // TODO: ultimately, programmatically linked nodes have to be resolved // at the end. // if info := c.cursor.file; info != nil { // done := map[*ast.ImportSpec]bool{} // for _, ident := range info.importPatch { // spec := ident.Node.(*ast.ImportSpec) // if done[spec] { // continue // } // done[spec] = true // path, _ := strconv.Unquote(spec.Path) // ident.Name = // } // } return c.decls } func apply[N ast.Node](v applyVisitor, parent Cursor, nodePtr *N) { node := *nodePtr c := newCursor(parent, node, nodePtr) applyCursor(v, c) if ast.Node(node) != c.node { *nodePtr = c.node.(N) } } func applyList[N ast.Node](v applyVisitor, parent Cursor, list []N) { c := newCursor(parent, nil, nil) for i, node := range list { c.index = i c.node = node c.typ = &list[i] applyCursor(v, c) if ast.Node(node) != c.node { list[i] = c.node.(N) } } } // applyCursor traverses an AST in depth-first order: It starts by calling // v.Visit(node); node must not be nil. If the visitor w returned by // v.Visit(node) is not nil, apply is invoked recursively with visitor // w for each of the non-nil children of node, followed by a call of // w.Visit(nil). func applyCursor(v applyVisitor, c Cursor) { if v = v.Before(c); v == nil { return } node := c.Node() // TODO: record the comment groups and interleave with the values like for // parsing and printing? applyList(v, c, ast.Comments(node)) // apply children // (the order of the cases matches the order // of the corresponding node types in go) switch n := node.(type) { // Comments and fields case *ast.Comment: // nothing to do case *ast.CommentGroup: applyList(v, c, n.List) case *ast.Attribute: // nothing to do case *ast.Field: apply(v, c, &n.Label) if n.Value != nil { apply(v, c, &n.Value) } applyList(v, c, n.Attrs) case *ast.StructLit: n.Elts = applyDeclList(v, c, n.Elts) // Expressions case *ast.BottomLit, *ast.BadExpr, *ast.Ident, *ast.BasicLit: // nothing to do case *ast.Interpolation: applyList(v, c, n.Elts) case *ast.ListLit: applyList(v, c, n.Elts) case *ast.Ellipsis: if n.Type != nil { apply(v, c, &n.Type) } case *ast.ParenExpr: apply(v, c, &n.X) case *ast.SelectorExpr: apply(v, c, &n.X) apply(v, c, &n.Sel) case *ast.IndexExpr: apply(v, c, &n.X) apply(v, c, &n.Index) case *ast.SliceExpr: apply(v, c, &n.X) if n.Low != nil { apply(v, c, &n.Low) } if n.High != nil { apply(v, c, &n.High) } case *ast.CallExpr: apply(v, c, &n.Fun) applyList(v, c, n.Args) case *ast.UnaryExpr: apply(v, c, &n.X) case *ast.BinaryExpr: apply(v, c, &n.X) apply(v, c, &n.Y) // Declarations case *ast.ImportSpec: if n.Name != nil { apply(v, c, &n.Name) } apply(v, c, &n.Path) case *ast.BadDecl: // nothing to do case *ast.ImportDecl: applyList(v, c, n.Specs) case *ast.EmbedDecl: apply(v, c, &n.Expr) case *ast.LetClause: apply(v, c, &n.Ident) apply(v, c, &n.Expr) case *ast.Alias: apply(v, c, &n.Ident) apply(v, c, &n.Expr) case *ast.Comprehension: applyList(v, c, n.Clauses) apply(v, c, &n.Value) // Files and packages case *ast.File: n.Decls = applyDeclList(v, c, n.Decls) case *ast.Package: apply(v, c, &n.Name) case *ast.ForClause: if n.Key != nil { apply(v, c, &n.Key) } apply(v, c, &n.Value) apply(v, c, &n.Source) case *ast.IfClause: apply(v, c, &n.Condition) default: panic(fmt.Sprintf("Walk: unexpected node type %T", n)) } v.After(c) } type applier struct { before func(Cursor) bool after func(Cursor) bool commentStack []commentFrame current commentFrame } type commentFrame struct { cg []*ast.CommentGroup pos int8 } func (f *applier) Before(c Cursor) applyVisitor { node := c.Node() if f.before == nil || (f.before(c) && node == c.Node()) { f.commentStack = append(f.commentStack, f.current) f.current = commentFrame{cg: ast.Comments(node)} f.visitComments(c, f.current.pos) return f } return nil } func (f *applier) After(c Cursor) bool { f.visitComments(c, 127) p := len(f.commentStack) - 1 f.current = f.commentStack[p] f.commentStack = f.commentStack[:p] f.current.pos++ if f.after != nil { f.after(c) } return true } func (f *applier) visitComments(p Cursor, pos int8) { c := &f.current for i, cg := range c.cg { if cg.Position == pos { continue } cursor := newCursor(p, cg, cg) if f.before == nil || (f.before(cursor) && !cursor.replaced) { for j, c := range cg.List { cursor := newCursor(p, c, &c) if f.before == nil || (f.before(cursor) && !cursor.replaced) { if f.after != nil { f.after(cursor) } } cg.List[j] = cursor.node.(*ast.Comment) } if f.after != nil { f.after(cursor) } } c.cg[i] = cursor.node.(*ast.CommentGroup) } } cue-lang-cue-db9cc73/cue/ast/astutil/apply_test.go000066400000000000000000000132241474664451600222450ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil_test import ( "strings" "testing" "github.com/go-quicktest/qt" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/format" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" ) func TestApply(t *testing.T) { testCases := []struct { name string in string out string before func(astutil.Cursor) bool after func(astutil.Cursor) bool }{{ // This should pass }, { name: "insert before", in: ` // foo is a foo: { a: 3 } `, out: ` iam: new // foo is a foo: { iam: new a: 3 } `, before: func(c astutil.Cursor) bool { switch c.Node().(type) { case *ast.Field: c.InsertBefore(&ast.Field{ Label: ast.NewIdent("iam"), Value: ast.NewIdent("new"), }) } return true }, }, { name: "insert after", in: ` foo: { a: 3 @test() } `, out: ` foo: { a: 3 @test() iam: new } iam: new `, before: func(c astutil.Cursor) bool { switch c.Node().(type) { case *ast.Field: c.InsertAfter(&ast.Field{ Label: ast.NewIdent("iam"), Value: ast.NewIdent("new"), }) } return true }, }, { name: "insert after recursive", in: ` foo: { a: 3 @test() } `, out: ` foo: { a: 3 @test() iam: { here: new there: new } everywhere: new } iam: { here: new there: new } everywhere: new `, before: func(c astutil.Cursor) bool { switch x := c.Node().(type) { case *ast.Field: switch x.Label.(*ast.Ident).Name { default: c.InsertAfter(astutil.ApplyRecursively(&ast.Field{ Label: ast.NewIdent("iam"), Value: ast.NewStruct(ast.NewIdent("here"), ast.NewIdent("new")), })) case "iam": c.InsertAfter(&ast.Field{ Label: ast.NewIdent("everywhere"), Value: ast.NewIdent("new"), }) case "here": c.InsertAfter(&ast.Field{ Label: ast.NewIdent("there"), Value: ast.NewIdent("new"), }) case "everywhere": } } return true }}, { name: "templates", in: ` foo: { a: [string]: c: 3 } `, out: ` foo: { a: [string]: { c: 3 iam: new } } `, before: func(c astutil.Cursor) bool { switch x := c.Node().(type) { case *ast.Field: if _, ok := x.Value.(*ast.StructLit); !ok { c.InsertAfter(&ast.Field{ Label: ast.NewIdent("iam"), Value: ast.NewIdent("new"), }) } } return true }, }, { name: "replace", in: ` // keep comment a: "string" // and this one b: 3 c: [ 1, 2, 8, 4 ] d: "\(foo) is \(0)" `, out: ` // keep comment a: s // and this one b: 4 c: [4, 4, 4, 4] d: "\(foo) is \(4)" `, before: func(c astutil.Cursor) bool { switch x := c.Node().(type) { case *ast.BasicLit: switch x.Kind { case token.STRING: if c.Index() < 0 { c.Replace(ast.NewIdent("s")) } case token.INT: c.Replace(ast.NewLit(token.INT, "4")) } } return true }, }, { name: "delete", in: ` z: 0 a: "foo" b: 3 b: "bar" c: 2 `, out: ` a: "foo" b: "bar" `, before: func(c astutil.Cursor) bool { f, ok := c.Node().(*ast.Field) if !ok { return true } switch x := f.Value.(type) { case *ast.BasicLit: switch x.Kind { case token.INT: c.Delete() } } return true }, }, { name: "comments", in: ` // test a: "string" `, out: ` // 1, 2, 3 a: "string" `, before: func(c astutil.Cursor) bool { switch c.Node().(type) { case *ast.Comment: c.Replace(&ast.Comment{Text: "// 1, 2, 3"}) } return true }, }, { name: "comments after", in: ` // test a: "string" `, out: ` // 1, 2, 3 a: "string" `, after: func(c astutil.Cursor) bool { switch c.Node().(type) { case *ast.Comment: c.Replace(&ast.Comment{Text: "// 1, 2, 3"}) } return true }, }, { name: "imports add", in: ` a: "string" `, out: ` import list6c6973 "list" a: list6c6973 `, after: func(c astutil.Cursor) bool { switch c.Node().(type) { case *ast.BasicLit: c.Replace(c.Import("list")) } return true }, }, { name: "imports add to", in: `package foo import "math" a: 3 `, out: `package foo import ( "math" list6c6973 "list" ) a: list6c6973 `, after: func(c astutil.Cursor) bool { switch x := c.Node().(type) { case *ast.BasicLit: if x.Kind == token.INT { c.Replace(c.Import("list")) } } return true }, }, { name: "imports duplicate", in: `package foo import "list" a: 3 `, out: `package foo import ( "list" list6c6973 "list" ) a: list6c6973 `, after: func(c astutil.Cursor) bool { switch x := c.Node().(type) { case *ast.BasicLit: if x.Kind == token.INT { c.Replace(c.Import("list")) } } return true }, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { f, err := parser.ParseFile(tc.name, tc.in, parser.ParseComments) if err != nil { t.Fatal(err) } n := astutil.Apply(f, tc.before, tc.after) b, err := format.Node(n) qt.Assert(t, qt.IsNil(err)) got := strings.TrimSpace(string(b)) want := strings.TrimSpace(tc.out) qt.Assert(t, qt.Equals(got, want)) }) } } cue-lang-cue-db9cc73/cue/ast/astutil/file.go000066400000000000000000000022241474664451600207760ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil import ( "cuelang.org/go/cue/ast" "cuelang.org/go/cue/token" ) // ToFile converts an expression to a File. It will create an import section for // any of the identifiers in x that refer to an import and will unshadow // references as appropriate. func ToFile(x ast.Expr) (*ast.File, error) { var f *ast.File if st, ok := x.(*ast.StructLit); ok { f = &ast.File{Decls: st.Elts} } else { ast.SetRelPos(x, token.NoSpace) f = &ast.File{Decls: []ast.Decl{&ast.EmbedDecl{Expr: x}}} } if err := Sanitize(f); err != nil { return nil, err } return f, nil } cue-lang-cue-db9cc73/cue/ast/astutil/file_test.go000066400000000000000000000043561474664451600220450ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil_test import ( "strings" "testing" "github.com/google/go-cmp/cmp" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/format" "cuelang.org/go/cue/token" _ "cuelang.org/go/pkg" ) func TestToFile(t *testing.T) { mat := ast.NewIdent("math") mat.Node = ast.NewImport(nil, "math") pi := ast.NewSel(mat, "Pi") testCases := []struct { desc string expr ast.Expr want string }{{ desc: "add import", expr: ast.NewBinExpr(token.ADD, ast.NewLit(token.INT, "1"), pi), want: "4.141592653589793238462643383279503", }, { desc: "resolve unresolved within struct", expr: ast.NewStruct( ast.NewIdent("a"), ast.NewString("foo"), ast.NewIdent("b"), ast.NewIdent("a"), ), want: `{ a: "foo" b: "foo" }`, }, { desc: "unshadow", expr: func() ast.Expr { ident := ast.NewIdent("a") ref := ast.NewIdent("a") ref.Node = ident return ast.NewStruct( ident, ast.NewString("bar"), ast.NewIdent("c"), ast.NewStruct( ast.NewIdent("a"), ast.NewString("foo"), ast.NewIdent("b"), ref, // refers to outer `a`. )) }(), want: `{ a: "bar" c: { a: "foo" b: "bar" } }`, }} for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { f, err := astutil.ToFile(tc.expr) if err != nil { t.Fatal(err) } v := cuecontext.New().BuildFile(f) if err := v.Err(); err != nil { t.Fatal(err) } b, err := format.Node(v.Syntax(cue.Concrete(true))) if err != nil { t.Fatal(err) } got := string(b) want := strings.TrimLeft(tc.want, "\n") if got != want { t.Error(cmp.Diff(want, got)) } }) } } cue-lang-cue-db9cc73/cue/ast/astutil/resolve.go000066400000000000000000000262661474664451600215520ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file implements scopes and the objects they contain. package astutil import ( "fmt" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/token" ) // An ErrFunc processes errors. type ErrFunc func(pos token.Pos, msg string, args ...interface{}) // TODO: future development // // Resolution currently assigns values along the table below. This is based on // Go's resolver and is not quite convenient for CUE's purposes. For one, CUE // allows manually setting resolution and than call astutil.Sanitize to // normalize the ast.File. Manually assigning resolutions according to the // below table is rather tedious though. // // Instead of using the Scope and Node fields in identifiers, we suggest the // following assignments: // // Reference Node // an Decl or Clause // Ident *Ident // The identifier in References (optional) // // References always refers to the direct element in the scope in which the // identifier occurs, not the final value, so: *Field, *LetClause, *ForClause, // etc. In case Ident is defined, it must be the same pointer as the // referencing identifier. In case it is not defined, the Name of the // referencing identifier can be used to locate the proper identifier in the // referenced node. // // The Scope field in the original design then loses its function. // // Type of reference Scope Node // Let Clause File/Struct LetClause // Alias declaration File/Struct Alias (deprecated) // Illegal Reference File/Struct // Value // X in a: X=y Field Alias // Fields // X in X: y File/Struct Expr (y) // X in X=x: y File/Struct Field // X in X=(x): y File/Struct Field // X in X="\(x)": y File/Struct Field // X in [X=x]: y Field Expr (x) // X in X=[x]: y Field Field // // for k, v in ForClause Ident // let x = y LetClause Ident // // Fields inside lambda // Label Field Expr // Value Field Field // Pkg nil ImportSpec // Resolve resolves all identifiers in a file. Unresolved identifiers are // recorded in Unresolved. It will not overwrite already resolved values. func Resolve(f *ast.File, errFn ErrFunc) { walkVisitor(f, &scope{errFn: errFn, identFn: resolveIdent}) } // Resolve resolves all identifiers in an expression. // It will not overwrite already resolved values. func ResolveExpr(e ast.Expr, errFn ErrFunc) { f := &ast.File{} walkVisitor(e, &scope{file: f, errFn: errFn, identFn: resolveIdent}) } // A Scope maintains the set of named language entities declared // in the scope and a link to the immediately surrounding (outer) // scope. type scope struct { file *ast.File outer *scope node ast.Node index map[string]entry inField bool identFn func(s *scope, n *ast.Ident) bool nameFn func(name string) errFn func(p token.Pos, msg string, args ...interface{}) } type entry struct { node ast.Node link ast.Node // Alias, LetClause, or Field } func newScope(f *ast.File, outer *scope, node ast.Node, decls []ast.Decl) *scope { const n = 4 // initial scope capacity s := &scope{ file: f, outer: outer, node: node, index: make(map[string]entry, n), identFn: outer.identFn, nameFn: outer.nameFn, errFn: outer.errFn, } for _, d := range decls { switch x := d.(type) { case *ast.Field: label := x.Label if a, ok := x.Label.(*ast.Alias); ok { name := a.Ident.Name if _, ok := a.Expr.(*ast.ListLit); !ok { s.insert(name, x, a) } } // default: name, isIdent, _ := ast.LabelName(label) if isIdent { v := x.Value // Avoid interpreting value aliases at this point. if a, ok := v.(*ast.Alias); ok { v = a.Expr } s.insert(name, v, x) } case *ast.LetClause: name, isIdent, _ := ast.LabelName(x.Ident) if isIdent { s.insert(name, x, x) } case *ast.Alias: name, isIdent, _ := ast.LabelName(x.Ident) if isIdent { s.insert(name, x, x) } case *ast.ImportDecl: for _, spec := range x.Specs { info, _ := ParseImportSpec(spec) s.insert(info.Ident, spec, spec) } } } return s } func (s *scope) isLet(n ast.Node) bool { if _, ok := s.node.(*ast.Field); ok { return true } switch n.(type) { case *ast.LetClause, *ast.Alias, *ast.Field: return true } return false } func (s *scope) mustBeUnique(n ast.Node) bool { if _, ok := s.node.(*ast.Field); ok { return true } switch n.(type) { // TODO: add *ast.ImportSpec when some implementations are moved over to // Sanitize. case *ast.ImportSpec, *ast.LetClause, *ast.Alias, *ast.Field: return true } return false } func (s *scope) insert(name string, n, link ast.Node) { if name == "" { return } if s.nameFn != nil { s.nameFn(name) } // TODO: record both positions. if outer, _, existing := s.lookup(name); existing.node != nil { if s.isLet(n) != outer.isLet(existing.node) { s.errFn(n.Pos(), "cannot have both alias and field with name %q in same scope", name) return } else if s.mustBeUnique(n) || outer.mustBeUnique(existing.node) { if outer == s { if _, ok := existing.node.(*ast.ImportSpec); ok { return // TODO: // s.errFn(n.Pos(), "conflicting declaration %s\n"+ // "\tprevious declaration at %s", // name, existing.node.Pos()) } else { s.errFn(n.Pos(), "alias %q redeclared in same scope", name) } return } // TODO: Should we disallow shadowing of aliases? // This was the case, but it complicates the transition to // square brackets. The spec says allow it. // s.errFn(n.Pos(), "alias %q already declared in enclosing scope", name) } } s.index[name] = entry{node: n, link: link} } func (s *scope) resolveScope(name string, node ast.Node) (scope ast.Node, e entry, ok bool) { last := s for s != nil { if n, ok := s.index[name]; ok && node == n.node { if last.node == n.node { return nil, n, true } return s.node, n, true } s, last = s.outer, s } return nil, entry{}, false } func (s *scope) lookup(name string) (p *scope, obj ast.Node, node entry) { // TODO(#152): consider returning nil for obj if it is a reference to root. // last := s if name == "_" { return nil, nil, entry{} } for s != nil { if n, ok := s.index[name]; ok { if _, ok := n.node.(*ast.ImportSpec); ok { return s, nil, n } return s, s.node, n } // s, last = s.outer, s s = s.outer } return nil, nil, entry{} } func (s *scope) After(n ast.Node) {} func (s *scope) Before(n ast.Node) (w visitor) { switch x := n.(type) { case *ast.File: s := newScope(x, s, x, x.Decls) // Support imports. for _, d := range x.Decls { walkVisitor(d, s) } return nil case *ast.StructLit: return newScope(s.file, s, x, x.Elts) case *ast.Comprehension: s = scopeClauses(s, x.Clauses) walkVisitor(x.Value, s) return nil case *ast.Field: var n ast.Node = x.Label alias, ok := x.Label.(*ast.Alias) if ok { n = alias.Expr } switch label := n.(type) { case *ast.ParenExpr: walkVisitor(label, s) case *ast.Interpolation: walkVisitor(label, s) case *ast.ListLit: if len(label.Elts) != 1 { break } s = newScope(s.file, s, x, nil) if alias != nil { if name, _, _ := ast.LabelName(alias.Ident); name != "" { s.insert(name, x, alias) } } expr := label.Elts[0] if a, ok := expr.(*ast.Alias); ok { expr = a.Expr // Add to current scope, instead of the value's, and allow // references to bind to these illegally. // We need this kind of administration anyway to detect // illegal name clashes, and it allows giving better error // messages. This puts the burden on clients of this library // to detect illegal usage, though. s.insert(a.Ident.Name, a.Expr, a) } ast.Walk(expr, nil, func(n ast.Node) { if x, ok := n.(*ast.Ident); ok { for s := s; s != nil && !s.inField; s = s.outer { if _, ok := s.index[x.Name]; ok { s.errFn(n.Pos(), "reference %q in label expression refers to field against which it would be matched", x.Name) } } } }) walkVisitor(expr, s) } if n := x.Value; n != nil { if alias, ok := x.Value.(*ast.Alias); ok { // TODO: this should move into Before once decl attributes // have been fully deprecated and embed attributes are introduced. s = newScope(s.file, s, x, nil) s.insert(alias.Ident.Name, alias, x) n = alias.Expr } s.inField = true walkVisitor(n, s) s.inField = false } return nil case *ast.LetClause: // Disallow referring to the current LHS name. name := x.Ident.Name saved := s.index[name] delete(s.index, name) // The same name may still appear in another scope if x.Expr != nil { walkVisitor(x.Expr, s) } s.index[name] = saved return nil case *ast.Alias: // Disallow referring to the current LHS name. name := x.Ident.Name saved := s.index[name] delete(s.index, name) // The same name may still appear in another scope if x.Expr != nil { walkVisitor(x.Expr, s) } s.index[name] = saved return nil case *ast.ImportSpec: return nil case *ast.Attribute: // TODO: tokenize attributes, resolve identifiers and store the ones // that resolve in a list. case *ast.SelectorExpr: walkVisitor(x.X, s) return nil case *ast.Ident: if s.identFn(s, x) { return nil } } return s } func resolveIdent(s *scope, x *ast.Ident) bool { name, ok, _ := ast.LabelName(x) if !ok { // TODO: generate error return false } if _, obj, node := s.lookup(name); node.node != nil { switch x.Node { case nil: x.Node = node.node x.Scope = obj case node.node: x.Scope = obj default: // x.Node != node scope, _, ok := s.resolveScope(name, x.Node) if !ok { s.file.Unresolved = append(s.file.Unresolved, x) } x.Scope = scope } } else { s.file.Unresolved = append(s.file.Unresolved, x) } return true } func scopeClauses(s *scope, clauses []ast.Clause) *scope { for _, c := range clauses { switch x := c.(type) { case *ast.ForClause: walkVisitor(x.Source, s) s = newScope(s.file, s, x, nil) if x.Key != nil { s.insert(x.Key.Name, x.Key, x) } s.insert(x.Value.Name, x.Value, x) case *ast.LetClause: walkVisitor(x.Expr, s) s = newScope(s.file, s, x, nil) s.insert(x.Ident.Name, x.Ident, x) default: walkVisitor(c, s) } } return s } // Debugging support func (s *scope) String() string { var b strings.Builder fmt.Fprintf(&b, "scope %p {", s) if s != nil && len(s.index) > 0 { fmt.Fprintln(&b) for name := range s.index { fmt.Fprintf(&b, "\t%v\n", name) } } fmt.Fprintf(&b, "}\n") return b.String() } cue-lang-cue-db9cc73/cue/ast/astutil/resolve_test.go000066400000000000000000000034671474664451600226070ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil_test import ( "fmt" "path/filepath" "testing" "text/tabwriter" "cuelang.org/go/cue/ast" "cuelang.org/go/internal/astinternal" "cuelang.org/go/internal/cuetxtar" ) func TestResolve(t *testing.T) { test := cuetxtar.TxTarTest{ Root: "./testdata/resolve", Name: "resolve", } test.Run(t, func(t *cuetxtar.Test) { a := t.Instance() for _, f := range a.Files { if filepath.Ext(f.Filename) != ".cue" { continue } identMap := map[ast.Node]int{} ast.Walk(f, func(n ast.Node) bool { switch n.(type) { case *ast.File, *ast.StructLit, *ast.Field, *ast.ImportSpec, *ast.Ident, *ast.ForClause, *ast.LetClause, *ast.Alias: identMap[n] = len(identMap) + 1 } return true }, nil) // Resolve was already called. base := filepath.Base(f.Filename) b := t.Writer(base[:len(base)-len(".cue")]) w := tabwriter.NewWriter(b, 0, 4, 1, ' ', 0) ast.Walk(f, func(n ast.Node) bool { if x, ok := n.(*ast.Ident); ok { fmt.Fprintf(w, "%d[%s]:\tScope: %d[%T]\tNode: %d[%s]\n", identMap[x], astinternal.DebugStr(x), identMap[x.Scope], x.Scope, identMap[x.Node], astinternal.DebugStr(x.Node)) } return true }, nil) w.Flush() fmt.Fprint(b) } }) } cue-lang-cue-db9cc73/cue/ast/astutil/sanitize.go000066400000000000000000000217741474664451600217200ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil import ( "fmt" "math/rand" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" ) // TODO: // - handle comprehensions // - change field from foo to "foo" if it isn't referenced, rather than // relying on introducing a unique alias. // - change a predeclared identifier reference to use the __ident form, // instead of introducing an alias. // Sanitize rewrites File f in place to be well-formed after automated // construction of an AST. // // Rewrites: // - auto inserts imports associated with Idents // - unshadows imports associated with idents // - unshadows references for identifiers that were already resolved. func Sanitize(f *ast.File) error { z := &sanitizer{ file: f, rand: rand.New(rand.NewSource(808)), names: map[string]bool{}, importMap: map[string]*ast.ImportSpec{}, referenced: map[ast.Node]bool{}, altMap: map[ast.Node]string{}, } // Gather all names. walkVisitor(f, &scope{ errFn: z.errf, nameFn: z.addName, identFn: z.markUsed, }) if z.errs != nil { return z.errs } // Add imports and unshadow. s := &scope{ file: f, errFn: z.errf, identFn: z.handleIdent, index: make(map[string]entry), } z.fileScope = s walkVisitor(f, s) if z.errs != nil { return z.errs } z.cleanImports() return z.errs } type sanitizer struct { file *ast.File fileScope *scope rand *rand.Rand // names is all used names. Can be used to determine a new unique name. names map[string]bool referenced map[ast.Node]bool // altMap defines an alternative name for an existing entry link (a field, // alias or let clause). As new names are globally unique, they can be // safely reused for any unshadowing. altMap map[ast.Node]string importMap map[string]*ast.ImportSpec errs errors.Error } func (z *sanitizer) errf(p token.Pos, msg string, args ...interface{}) { z.errs = errors.Append(z.errs, errors.Newf(p, msg, args...)) } func (z *sanitizer) addName(name string) { z.names[name] = true } func (z *sanitizer) addRename(base string, n ast.Node) (alt string, new bool) { if name, ok := z.altMap[n]; ok { return name, false } name := z.uniqueName(base, false) z.altMap[n] = name return name, true } func (z *sanitizer) unshadow(parent ast.Node, base string, link ast.Node) string { name, ok := z.altMap[link] if !ok { name = z.uniqueName(base, false) z.altMap[link] = name // Insert new let clause at top to refer to a declaration in possible // other files. let := &ast.LetClause{ Ident: ast.NewIdent(name), Expr: ast.NewIdent(base), } var decls *[]ast.Decl switch x := parent.(type) { case *ast.File: decls = &x.Decls case *ast.StructLit: decls = &x.Elts default: panic(fmt.Sprintf("impossible scope type %T", parent)) } i := 0 for ; i < len(*decls); i++ { if (*decls)[i] == link { break } if f, ok := (*decls)[i].(*ast.Field); ok && f.Label == link { break } } if i > 0 { ast.SetRelPos(let, token.NewSection) } a := append((*decls)[:i:i], let) *decls = append(a, (*decls)[i:]...) } return name } func (z *sanitizer) markUsed(s *scope, n *ast.Ident) bool { if n.Node != nil { return false } _, _, entry := s.lookup(n.String()) z.referenced[entry.link] = true return true } func (z *sanitizer) cleanImports() { var fileImports []*ast.ImportSpec z.file.VisitImports(func(decl *ast.ImportDecl) { newLen := 0 for _, spec := range decl.Specs { if _, ok := z.referenced[spec]; ok { fileImports = append(fileImports, spec) decl.Specs[newLen] = spec newLen++ } } decl.Specs = decl.Specs[:newLen] }) z.file.Imports = fileImports // Ensure that the first import always starts a new section // so that if the file has a comment, it won't be associated with // the import comment rather than the file. first := true z.file.VisitImports(func(decl *ast.ImportDecl) { if first { ast.SetRelPos(decl, token.NewSection) first = false } }) } func (z *sanitizer) handleIdent(s *scope, n *ast.Ident) bool { if n.Node == nil { return true } _, _, node := s.lookup(n.Name) if node.node == nil { spec, ok := n.Node.(*ast.ImportSpec) if !ok { // Clear node. A reference may have been moved to a different // file. If not, it should be an error. n.Node = nil n.Scope = nil return false } _ = z.addImport(spec) info, _ := ParseImportSpec(spec) z.fileScope.insert(info.Ident, spec, spec) return true } if x, ok := n.Node.(*ast.ImportSpec); ok { xi, _ := ParseImportSpec(x) if y, ok := node.node.(*ast.ImportSpec); ok { yi, _ := ParseImportSpec(y) if xi.ID == yi.ID { // name must be identical as a result of lookup. z.referenced[y] = true n.Node = x n.Scope = nil return false } } // Either: // - the import is shadowed // - an incorrect import is matched // In all cases we need to create a new import with a unique name or // use a previously created one. spec := z.importMap[xi.ID] if spec == nil { name := z.uniqueName(xi.Ident, false) spec = z.addImport(&ast.ImportSpec{ Name: ast.NewIdent(name), Path: x.Path, }) z.importMap[xi.ID] = spec z.fileScope.insert(name, spec, spec) } info, _ := ParseImportSpec(spec) // TODO(apply): replace n itself directly n.Name = info.Ident n.Node = spec n.Scope = nil return false } if node.node == n.Node { return true } // n.Node != node and are both not nil and n.Node is not an ImportSpec. // This means that either n.Node is illegal or shadowed. // Look for the scope in which n.Node is defined and add an alias or let. parent, e, ok := s.resolveScope(n.Name, n.Node) if !ok { // The node isn't within a legal scope within this file. It may only // possibly shadow a value of another file. We add a top-level let // clause to refer to this value. // TODO(apply): better would be to have resolve use Apply so that we can replace // the entire ast.Ident, rather than modifying it. // TODO: resolve to new node or rely on another pass of Resolve? n.Name = z.unshadow(z.file, n.Name, n) n.Node = nil n.Scope = nil return false } var name string // var isNew bool switch x := e.link.(type) { case *ast.Field: // referring to regular field. name, ok = z.altMap[x] if ok { break } // If this field has not alias, introduce one with a unique name. // If this has an alias, also introduce a new name. There is a // possibility that the alias can be used, but it is easier to just // assign a new name, assuming this case is rather rare. switch y := x.Label.(type) { case *ast.Alias: name = z.unshadow(parent, y.Ident.Name, y) case *ast.Ident: var isNew bool name, isNew = z.addRename(y.Name, x) if isNew { ident := ast.NewIdent(name) // Move formatting and comments from original label to alias // identifier. CopyMeta(ident, y) ast.SetRelPos(y, token.NoRelPos) ast.SetComments(y, nil) x.Label = &ast.Alias{Ident: ident, Expr: y} } default: // This is an illegal reference. return false } case *ast.LetClause: name = z.unshadow(parent, x.Ident.Name, x) case *ast.Alias: name = z.unshadow(parent, x.Ident.Name, x) default: panic(fmt.Sprintf("unexpected link type %T", e.link)) } // TODO(apply): better would be to have resolve use Apply so that we can replace // the entire ast.Ident, rather than modifying it. n.Name = name n.Node = nil n.Scope = nil return true } // uniqueName returns a new name globally unique name of the form // base_NN ... base_NNNNNNNNNNNNNN or _base or the same pattern with a '_' // prefix if hidden is true. // // It prefers short extensions over large ones, while ensuring the likelihood of // fast termination is high. There are at least two digits to make it visually // clearer this concerns a generated number. func (z *sanitizer) uniqueName(base string, hidden bool) string { if hidden && !strings.HasPrefix(base, "_") { base = "_" + base if !z.names[base] { z.names[base] = true return base } } const mask = 0xff_ffff_ffff_ffff // max bits; stay clear of int64 overflow const shift = 4 // rate of growth for n := int64(0x10); ; n = int64(mask&((n< 3 { x: [k, v, y] } -- out/resolve/in -- 3[src]: Scope: 0[] Node: 0[] 6[foo]: Scope: 0[] Node: 0[] 8[k]: Scope: 0[] Node: 0[] 9[v]: Scope: 0[] Node: 0[] 10[src]: Scope: 1[*ast.File] Node: 0[[{foo: 3}]] 12[y]: Scope: 0[] Node: 0[] 13[v]: Scope: 7[*ast.ForClause] Node: 9[v] 14[foo]: Scope: 0[] Node: 0[] 15[y]: Scope: 11[*ast.LetClause] Node: 12[y] 18[x]: Scope: 0[] Node: 0[] 19[k]: Scope: 7[*ast.ForClause] Node: 8[k] 20[v]: Scope: 7[*ast.ForClause] Node: 9[v] 21[y]: Scope: 11[*ast.LetClause] Node: 12[y] -- issue946.cue -- x: {for a in a {}} y: {for aa in a {}} -- out/resolve/issue946 -- 3[x]: Scope: 0[] Node: 0[] 6[a]: Scope: 0[] Node: 0[] 7[a]: Scope: 0[] Node: 0[] 10[y]: Scope: 0[] Node: 0[] 13[aa]: Scope: 0[] Node: 0[] 14[a]: Scope: 0[] Node: 0[] cue-lang-cue-db9cc73/cue/ast/astutil/testdata/resolve/fieldalias.txtar000066400000000000000000000015331474664451600262030ustar00rootroot00000000000000-- in.cue -- X=a: int b: a c: X -- out/resolve/in -- 4[X]: Scope: 0[] Node: 0[] 5[a]: Scope: 0[] Node: 0[] 6[int]: Scope: 0[] Node: 0[] 8[b]: Scope: 0[] Node: 0[] 9[a]: Scope: 1[*ast.File] Node: 6[int] 11[c]: Scope: 0[] Node: 0[] 12[X]: Scope: 1[*ast.File] Node: 2[X=a: int] -- dynamic.cue -- X=("foo"): int Y="\(X)": string a: X b: Y -- out/resolve/dynamic -- 4[X]: Scope: 0[] Node: 0[] 5[int]: Scope: 0[] Node: 0[] 8[Y]: Scope: 0[] Node: 0[] 9[X]: Scope: 1[*ast.File] Node: 2[X=("foo"): int] 10[string]: Scope: 0[] Node: 0[] 12[a]: Scope: 0[] Node: 0[] 13[X]: Scope: 1[*ast.File] Node: 2[X=("foo"): int] 15[b]: Scope: 0[] Node: 0[] 16[Y]: Scope: 1[*ast.File] Node: 6[Y="\(X)": string] cue-lang-cue-db9cc73/cue/ast/astutil/testdata/resolve/labels.txtar000066400000000000000000000021361474664451600253500ustar00rootroot00000000000000-- in.cue -- [X=string]: name: X a: X Z=[string]: {x: string, y: Z.x} c: Z // `_` should not resolve. _: 1 x: _ for _ in [1] {a: _} -- out/resolve/in -- 4[X]: Scope: 0[] Node: 0[] 5[string]: Scope: 0[] Node: 0[] 8[name]: Scope: 0[] Node: 0[] 9[X]: Scope: 2[*ast.Field] Node: 5[string] 11[a]: Scope: 0[] Node: 0[] 12[X]: Scope: 0[] Node: 0[] 15[Z]: Scope: 0[] Node: 0[] 16[string]: Scope: 0[] Node: 0[] 19[x]: Scope: 0[] Node: 0[] 20[string]: Scope: 0[] Node: 0[] 22[y]: Scope: 0[] Node: 0[] 23[Z]: Scope: 13[*ast.Field] Node: 13[Z=[string]: {x: string, y: Z.x}] 24[x]: Scope: 0[] Node: 0[] 26[c]: Scope: 0[] Node: 0[] 27[Z]: Scope: 0[] Node: 0[] 29[_]: Scope: 0[] Node: 0[] 31[x]: Scope: 0[] Node: 0[] 32[_]: Scope: 0[] Node: 0[] 34[_]: Scope: 0[] Node: 0[] 37[a]: Scope: 0[] Node: 0[] 38[_]: Scope: 0[] Node: 0[] cue-lang-cue-db9cc73/cue/ast/astutil/testdata/resolve/let.txtar000066400000000000000000000004601474664451600246700ustar00rootroot00000000000000-- let.cue -- b: X let X = int a: X -- out/resolve/let -- 3[b]: Scope: 0[] Node: 0[] 4[X]: Scope: 1[*ast.File] Node: 5[let X=int] 6[X]: Scope: 0[] Node: 0[] 7[int]: Scope: 0[] Node: 0[] 9[a]: Scope: 0[] Node: 0[] 10[X]: Scope: 1[*ast.File] Node: 5[let X=int] cue-lang-cue-db9cc73/cue/ast/astutil/testdata/resolve/value.txtar000066400000000000000000000003731474664451600252230ustar00rootroot00000000000000-- in.cue -- b: X={ c: X.a } -- out/resolve/in -- 3[b]: Scope: 0[] Node: 0[] 5[X]: Scope: 0[] Node: 0[] 8[c]: Scope: 0[] Node: 0[] 9[X]: Scope: 2[*ast.Field] Node: 4[X={c: X.a}] 10[a]: Scope: 0[] Node: 0[] cue-lang-cue-db9cc73/cue/ast/astutil/util.go000066400000000000000000000070571474664451600210450ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil import ( "path" "strconv" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/token" ) // ImportPathName derives the package name from the given import path. // // Examples: // // string string // foo.com/bar bar // foo.com/bar:baz baz func ImportPathName(id string) string { name := path.Base(id) if p := strings.LastIndexByte(name, ':'); p > 0 { name = name[p+1:] } return name } // ImportInfo describes the information contained in an ImportSpec. type ImportInfo struct { Ident string // identifier used to refer to the import PkgName string // name of the package ID string // full import path, including the name Dir string // import path, excluding the name } // ParseImportSpec returns the name and full path of an ImportSpec. func ParseImportSpec(spec *ast.ImportSpec) (info ImportInfo, err error) { str, err := strconv.Unquote(spec.Path.Value) if err != nil { return info, err } info.ID = str if p := strings.LastIndexByte(str, ':'); p > 0 { info.Dir = str[:p] info.PkgName = str[p+1:] } else { info.Dir = str info.PkgName = path.Base(str) } if spec.Name != nil { info.Ident = spec.Name.Name } else { info.Ident = info.PkgName } return info, nil } // CopyComments associates comments of one node with another. // It may change the relative position of comments. func CopyComments(to, from ast.Node) { if from == nil { return } ast.SetComments(to, ast.Comments(from)) } // CopyPosition sets the position of one node to another. func CopyPosition(to, from ast.Node) { if from == nil { return } ast.SetPos(to, from.Pos()) } // CopyMeta copies comments and position information from one node to another. // It returns the destination node. func CopyMeta(to, from ast.Node) ast.Node { if from == nil { return to } ast.SetComments(to, ast.Comments(from)) ast.SetPos(to, from.Pos()) return to } // insertImport looks up an existing import with the given name and path or will // add spec if it doesn't exist. It returns a spec in decls matching spec. func insertImport(decls *[]ast.Decl, spec *ast.ImportSpec) *ast.ImportSpec { x, _ := ParseImportSpec(spec) a := *decls var imports *ast.ImportDecl var orig *ast.ImportSpec p := 0 outer: for i := 0; i < len(a); i++ { d := a[i] switch t := d.(type) { default: break outer case *ast.Package: p = i + 1 case *ast.CommentGroup: p = i + 1 case *ast.Attribute: continue case *ast.ImportDecl: p = i + 1 imports = t for _, s := range t.Specs { y, _ := ParseImportSpec(s) if y.ID != x.ID { continue } orig = s if x.Ident == "" || y.Ident == x.Ident { return s } } } } // Import not found, add one. if imports == nil { imports = &ast.ImportDecl{} preamble := append(a[:p:p], imports) a = append(preamble, a[p:]...) *decls = a } if orig != nil { CopyComments(spec, orig) } imports.Specs = append(imports.Specs, spec) ast.SetRelPos(imports.Specs[0], token.NoRelPos) return spec } cue-lang-cue-db9cc73/cue/ast/astutil/util_test.go000066400000000000000000000032631474664451600220770ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil import ( "path" "testing" "github.com/google/go-cmp/cmp" "cuelang.org/go/cue/ast" ) func TestImportInfo(t *testing.T) { testCases := []struct { name string path string want ImportInfo }{ {"", "a.b/bar", ImportInfo{ Ident: "bar", PkgName: "bar", ID: "a.b/bar", Dir: "a.b/bar", }}, {"foo", "a.b/bar", ImportInfo{ Ident: "foo", PkgName: "bar", ID: "a.b/bar", Dir: "a.b/bar", }}, {"", "a.b/bar:foo", ImportInfo{ Ident: "foo", PkgName: "foo", ID: "a.b/bar:foo", Dir: "a.b/bar", }}, {"", "strings", ImportInfo{ Ident: "strings", PkgName: "strings", ID: "strings", Dir: "strings", }}, } for _, tc := range testCases { t.Run(path.Join(tc.name, tc.path), func(t *testing.T) { var ident *ast.Ident if tc.name != "" { ident = ast.NewIdent(tc.name) } got, err := ParseImportSpec(&ast.ImportSpec{ Name: ident, Path: ast.NewString(tc.path), }) if err != nil { t.Fatal(err) } if diff := cmp.Diff(got, tc.want); diff != "" { t.Error(diff) } }) } } cue-lang-cue-db9cc73/cue/ast/astutil/walk.go000066400000000000000000000033161474664451600210200ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package astutil import "cuelang.org/go/cue/ast" // walkVisitor traverses an AST in depth-first order with a [visitor]. // // TODO(mvdan): refactor away the need for walkVisitor; // Resolve and Sanitize should be able to use ast.Walk directly. func walkVisitor(node ast.Node, v visitor) { sv := &stackVisitor{stack: []visitor{v}} ast.Walk(node, sv.Before, sv.After) } // stackVisitor helps implement visitor support on top of ast.Walk. type stackVisitor struct { stack []visitor } func (v *stackVisitor) Before(node ast.Node) bool { current := v.stack[len(v.stack)-1] next := current.Before(node) if next == nil { return false } v.stack = append(v.stack, next) return true } func (v *stackVisitor) After(node ast.Node) { v.stack[len(v.stack)-1] = nil // set visitor to nil so it can be garbage collected v.stack = v.stack[:len(v.stack)-1] } // A visitor's before method is invoked for each node encountered by Walk. // If the result visitor w is true, Walk visits each of the children // of node with the visitor w, followed by a call of w.After. type visitor interface { Before(node ast.Node) (w visitor) After(node ast.Node) } cue-lang-cue-db9cc73/cue/ast/comments.go000066400000000000000000000025271474664451600202250ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ast // Comments returns all comments associated with a given node. func Comments(n Node) []*CommentGroup { c := n.commentInfo() if c == nil { return nil } return c.Comments() } // AddComment adds the given comment to the node if it supports it. // If a node does not support comments, such as for CommentGroup or Comment, // this call has no effect. func AddComment(n Node, cg *CommentGroup) { c := n.commentInfo() if c == nil { return } c.AddComment(cg) } // SetComments replaces all comments of n with the given set of comments. // If a node does not support comments, such as for CommentGroup or Comment, // this call has no effect. func SetComments(n Node, cgs []*CommentGroup) { c := n.commentInfo() if c == nil { return } c.SetComments(cgs) } cue-lang-cue-db9cc73/cue/ast/ident.go000066400000000000000000000070411474664451600174770ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ast import ( "strconv" "strings" "unicode" "unicode/utf8" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" ) func isLetter(ch rune) bool { return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch >= utf8.RuneSelf && unicode.IsLetter(ch) } func isDigit(ch rune) bool { // TODO(mpvl): Is this correct? return '0' <= ch && ch <= '9' || ch >= utf8.RuneSelf && unicode.IsDigit(ch) } // IsValidIdent reports whether str is a valid identifier. // Note that the underscore "_" string is considered valid, for top. func IsValidIdent(ident string) bool { if ident == "" { return false } consumed := false if strings.HasPrefix(ident, "_") { ident = ident[1:] consumed = true if len(ident) == 0 { return true } } if strings.HasPrefix(ident, "#") { ident = ident[1:] // Note: _#0 is not allowed by the spec, although _0 is. // TODO: set consumed to true here to allow #0. consumed = false } if !consumed { if r, _ := utf8.DecodeRuneInString(ident); isDigit(r) { return false } } for _, r := range ident { if isLetter(r) || isDigit(r) || r == '_' || r == '$' { continue } return false } return true } // LabelName reports the name of a label, whether it is an identifier // (it binds a value to a scope), and whether it is valid. // Keywords that are allowed in label positions are interpreted accordingly. // // Examples: // // Label Result // foo "foo" true nil // true "true" true nil // "foo" "foo" false nil // "x-y" "x-y" false nil // "foo "" false invalid string // "\(x)" "" false errors.Is(err, ErrIsExpression) // X=foo "foo" true nil func LabelName(l Label) (name string, isIdent bool, err error) { if a, ok := l.(*Alias); ok { l, _ = a.Expr.(Label) } switch n := l.(type) { case *ListLit: // An expression, but not one that can evaluated. return "", false, errors.Newf(l.Pos(), "cannot reference fields with square brackets labels outside the field value") case *Ident: name = n.Name if !IsValidIdent(name) { return "", false, errors.Newf(l.Pos(), "invalid identifier") } return name, true, err case *BasicLit: switch n.Kind { case token.STRING: // Use strconv to only allow double-quoted, single-line strings. name, err = strconv.Unquote(n.Value) if err != nil { err = errors.Newf(l.Pos(), "invalid") } case token.NULL, token.TRUE, token.FALSE: name = n.Value isIdent = true default: // TODO: allow numbers to be fields // This includes interpolation and template labels. return "", false, errors.Wrapf(ErrIsExpression, l.Pos(), "cannot use numbers as fields") } return name, isIdent, err default: // This includes interpolation and template labels. return "", false, errors.Wrapf(ErrIsExpression, l.Pos(), "label is an expression") } } // ErrIsExpression reports whether a label is an expression. // This error is never returned directly. Use [errors.Is]. var ErrIsExpression = errors.New("not a concrete label") cue-lang-cue-db9cc73/cue/ast/ident_test.go000066400000000000000000000061721474664451600205420ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ast_test import ( "errors" "strings" "testing" "github.com/go-quicktest/qt" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/format" "cuelang.org/go/cue/token" ) func TestLabelName(t *testing.T) { testCases := []struct { in ast.Label out string isIdent bool err bool expr bool }{{ in: ast.NewString("foo-bar"), out: "foo-bar", isIdent: false, }, { in: ast.NewString("8ball"), out: "8ball", isIdent: false, }, { in: ast.NewString("foo bar"), out: "foo bar", isIdent: false, }, { in: &ast.Ident{Name: "`foo`"}, err: true, }, { in: &ast.Ident{Name: ""}, out: "", isIdent: false, err: true, }, { in: &ast.Ident{Name: "#"}, out: "#", isIdent: true, }, { in: &ast.Ident{Name: "#0"}, out: "", isIdent: false, err: true, }, { in: &ast.Ident{Name: "_#"}, out: "_#", isIdent: true, err: false, }, { in: &ast.Ident{Name: "_"}, out: "_", isIdent: true, }, { in: &ast.Ident{Name: "_1"}, out: "_1", isIdent: true, }, { in: &ast.Ident{Name: "_#1"}, out: "", err: true, }, { in: &ast.Ident{Name: "8ball"}, out: "", isIdent: false, err: true, }, { in: &ast.Ident{Name: "_hidden"}, out: "_hidden", isIdent: true, }, { in: &ast.Ident{Name: "#A"}, out: "#A", isIdent: true, }, { in: &ast.Ident{Name: "#Def"}, out: "#Def", isIdent: true, }, { in: &ast.Ident{Name: "_#Def"}, out: "_#Def", isIdent: true, }, { in: &ast.Ident{Name: "#_Def"}, out: "#_Def", isIdent: true, }, { in: ast.NewBool(true), out: "true", isIdent: true, }, { in: &ast.BasicLit{Kind: token.STRING, Value: `"foo`}, out: "", isIdent: false, err: true, }, { in: &ast.Interpolation{Elts: []ast.Expr{ast.NewString("foo")}}, out: "", isIdent: false, err: true, expr: true, }} for _, tc := range testCases { b, _ := format.Node(tc.in) t.Run(string(b), func(t *testing.T) { if id, ok := tc.in.(*ast.Ident); ok && !strings.HasPrefix(id.Name, "`") { qt.Assert(t, qt.Equals(ast.IsValidIdent(id.Name), tc.isIdent)) } str, isIdent, err := ast.LabelName(tc.in) qt.Assert(t, qt.Equals(str, tc.out), qt.Commentf("value")) qt.Assert(t, qt.Equals(isIdent, tc.isIdent), qt.Commentf("isIdent")) qt.Assert(t, qt.Equals(err != nil, tc.err), qt.Commentf("err")) qt.Assert(t, qt.Equals(errors.Is(err, ast.ErrIsExpression), tc.expr), qt.Commentf("expr")) }) } } cue-lang-cue-db9cc73/cue/ast/walk.go000066400000000000000000000070721474664451600173360ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ast import ( "fmt" ) func walkList[N Node](list []N, before func(Node) bool, after func(Node)) { for _, node := range list { Walk(node, before, after) } } // Walk traverses an AST in depth-first order: It starts by calling f(node); // node must not be nil. If before returns true, Walk invokes f recursively for // each of the non-nil children of node, followed by a call of after. Both // functions may be nil. If before is nil, it is assumed to always return true. func Walk(node Node, before func(Node) bool, after func(Node)) { if before != nil && !before(node) { return } // TODO: record the comment groups and interleave with the values like for // parsing and printing? walkList(Comments(node), before, after) // walk children // (the order of the cases matches the order // of the corresponding node types in go) switch n := node.(type) { // Comments and fields case *Comment: // nothing to do case *CommentGroup: walkList(n.List, before, after) case *Attribute: // nothing to do case *Field: Walk(n.Label, before, after) if n.Value != nil { Walk(n.Value, before, after) } walkList(n.Attrs, before, after) case *Func: walkList(n.Args, before, after) Walk(n.Ret, before, after) case *StructLit: walkList(n.Elts, before, after) // Expressions case *BottomLit, *BadExpr, *Ident, *BasicLit: // nothing to do case *Interpolation: walkList(n.Elts, before, after) case *ListLit: walkList(n.Elts, before, after) case *Ellipsis: if n.Type != nil { Walk(n.Type, before, after) } case *ParenExpr: Walk(n.X, before, after) case *SelectorExpr: Walk(n.X, before, after) Walk(n.Sel, before, after) case *IndexExpr: Walk(n.X, before, after) Walk(n.Index, before, after) case *SliceExpr: Walk(n.X, before, after) if n.Low != nil { Walk(n.Low, before, after) } if n.High != nil { Walk(n.High, before, after) } case *CallExpr: Walk(n.Fun, before, after) walkList(n.Args, before, after) case *UnaryExpr: Walk(n.X, before, after) case *BinaryExpr: Walk(n.X, before, after) Walk(n.Y, before, after) // Declarations case *ImportSpec: if n.Name != nil { Walk(n.Name, before, after) } Walk(n.Path, before, after) case *BadDecl: // nothing to do case *ImportDecl: walkList(n.Specs, before, after) case *EmbedDecl: Walk(n.Expr, before, after) case *LetClause: Walk(n.Ident, before, after) Walk(n.Expr, before, after) case *Alias: Walk(n.Ident, before, after) Walk(n.Expr, before, after) case *Comprehension: walkList(n.Clauses, before, after) Walk(n.Value, before, after) // Files and packages case *File: walkList(n.Decls, before, after) case *Package: Walk(n.Name, before, after) case *ForClause: if n.Key != nil { Walk(n.Key, before, after) } Walk(n.Value, before, after) Walk(n.Source, before, after) case *IfClause: Walk(n.Condition, before, after) default: panic(fmt.Sprintf("Walk: unexpected node type %T", n)) } if after != nil { after(node) } } cue-lang-cue-db9cc73/cue/attribute.go000066400000000000000000000146371474664451600176210ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "fmt" "cuelang.org/go/cue/ast" "cuelang.org/go/internal" "cuelang.org/go/internal/core/export" ) // Attribute returns the attribute data for the given key. // The returned attribute will return an error for any of its methods if there // is no attribute for the requested key. func (v Value) Attribute(key string) Attribute { // look up the attributes if v.v == nil { return nonExistAttr(key) } // look up the attributes for _, a := range export.ExtractFieldAttrs(v.v) { k, _ := a.Split() if key != k { continue } return newAttr(internal.FieldAttr, a) } return nonExistAttr(key) } func newAttr(k internal.AttrKind, a *ast.Attribute) Attribute { key, body := a.Split() // Note: the body is always positioned just after // the opening ( after the key. x := internal.ParseAttrBody(a.Pos().Add(len(key)+1), body) x.Name = key x.Kind = k x.Pos = a.Pos() return Attribute{x} } func nonExistAttr(key string) Attribute { a := internal.NewNonExisting(key) a.Name = key a.Kind = internal.FieldAttr return Attribute{a} } // Attributes reports all field attributes for the Value. // // To retrieve attributes of multiple kinds, you can bitwise-or kinds together. // Use ValueKind to query attributes associated with a value. func (v Value) Attributes(mask AttrKind) []Attribute { if v.v == nil { return nil } attrs := []Attribute{} if mask&FieldAttr != 0 { for _, a := range export.ExtractFieldAttrs(v.v) { attrs = append(attrs, newAttr(internal.FieldAttr, a)) } } if mask&DeclAttr != 0 { for _, a := range export.ExtractDeclAttrs(v.v) { attrs = append(attrs, newAttr(internal.DeclAttr, a)) } } return attrs } // AttrKind indicates the location of an attribute within CUE source. type AttrKind int const ( // FieldAttr indicates a field attribute. // foo: bar @attr() FieldAttr AttrKind = AttrKind(internal.FieldAttr) // DeclAttr indicates a declaration attribute. // foo: { // @attr() // } DeclAttr AttrKind = AttrKind(internal.DeclAttr) // A ValueAttr is a bit mask to request any attribute that is locally // associated with a field, instead of, for instance, an entire file. ValueAttr AttrKind = FieldAttr | DeclAttr // TODO: Possible future attr kinds // ElemAttr (is a ValueAttr) // FileAttr (not a ValueAttr) // TODO: Merge: merge namesake attributes. ) // An Attribute contains metadata about a field. // // By convention, an attribute is split into positional arguments // according to the rules below. However, these are not mandatory. // To access the raw contents of an attribute, use [Attribute.Contents]. // // Arguments are of the form key[=value] where key and value each // consist of an arbitrary number of CUE tokens with balanced brackets // ((), [], and {}). These are the arguments retrieved by the // [Attribute] methods. // // Leading and trailing white space will be stripped from both key and // value. If there is no value and the key consists of exactly one // quoted string, it will be unquoted. type Attribute struct { attr internal.Attr } // Format implements fmt.Formatter. func (a Attribute) Format(w fmt.State, verb rune) { fmt.Fprintf(w, "@%s(%s)", a.attr.Name, a.attr.Body) } var _ fmt.Formatter = &Attribute{} // Name returns the name of the attribute, for instance, "json" for @json(...). func (a *Attribute) Name() string { return a.attr.Name } // Contents reports the full contents of an attribute within parentheses, so // contents in @attr(contents). func (a *Attribute) Contents() string { return a.attr.Body } // NumArgs reports the number of arguments parsed for this attribute. func (a *Attribute) NumArgs() int { return len(a.attr.Fields) } // Arg reports the contents of the ith comma-separated argument of a. // // If the argument contains an unescaped equals sign, it returns a key-value // pair. Otherwise it returns the contents in key. func (a *Attribute) Arg(i int) (key, value string) { // TODO: Returning the contents in key for a non-key-value argument // is counter to the original documentation for this method and // counter-intuitive too, but it remains that way to avoid breaking // backward compatibility. In the future it would be nice to // change it to return ("", value) in this case. f := a.attr.Fields[i] if f.Key() == "" { return f.Value(), "" } return f.Key(), f.Value() } // RawArg reports the raw contents of the ith comma-separated argument of a, // including surrounding spaces. func (a *Attribute) RawArg(i int) string { return a.attr.Fields[i].Text() } // Kind reports the type of location within CUE source where the attribute // was specified. func (a *Attribute) Kind() AttrKind { return AttrKind(a.attr.Kind) } // Err returns the error associated with this Attribute or nil if this // attribute is valid. func (a *Attribute) Err() error { return a.attr.Err } // String reports the possibly empty string value at the given position or // an error the attribute is invalid or if the position does not exist. func (a *Attribute) String(pos int) (string, error) { return a.attr.String(pos) } // Int reports the integer at the given position or an error if the attribute is // invalid, the position does not exist, or the value at the given position is // not an integer. func (a *Attribute) Int(pos int) (int64, error) { return a.attr.Int(pos) } // Flag reports whether an entry with the given name exists at position pos or // onwards or an error if the attribute is invalid or if the first pos-1 entries // are not defined. func (a *Attribute) Flag(pos int, key string) (bool, error) { return a.attr.Flag(pos, key) } // Lookup searches for an entry of the form key=value from position pos onwards // and reports the value if found. It reports an error if the attribute is // invalid or if the first pos-1 entries are not defined. func (a *Attribute) Lookup(pos int, key string) (val string, found bool, err error) { return a.attr.Lookup(pos, key) } cue-lang-cue-db9cc73/cue/attribute_test.go000066400000000000000000000220161474664451600206460ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/errors" "cuelang.org/go/internal/cuetdtest" ) func TestAttributes(t *testing.T) { const config = ` a: { a: 0 @foo(a,b,c=1) b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) } b: { @embed(foo) 3 } @field(foo) c1: {} @step(1) if true { c2: { @step(2a) } @step(2b) @step(2c) } c3: {} @step(3) if false { c4: { @step(4a) } @step(4b) @step(4c) } ` testCases := []struct { flags cue.AttrKind path string out string }{{ flags: cue.FieldAttr, path: "a.a", out: "[@foo(a,b,c=1)]", }, { flags: cue.FieldAttr, path: "a.b", out: "[@bar(a,b,c,d=1) @foo(a,,d=1)]", }, { flags: cue.DeclAttr, path: "b", out: "[@embed(foo)]", }, { flags: cue.FieldAttr, path: "b", out: "[@field(foo)]", }, { flags: cue.ValueAttr, path: "b", out: "[@field(foo) @embed(foo)]", }, { flags: cue.ValueAttr, path: "c1", out: "[@step(1)]", }, { flags: cue.DeclAttr, path: "c2", out: "[@step(2a)]", }, { flags: cue.FieldAttr, path: "c2", out: "[@step(2b)]", }, { flags: cue.DeclAttr, path: "", out: "[@step(2c)]", }, { flags: cue.ValueAttr | cue.FieldAttr, path: "c3", out: "[@step(3)]", }, { flags: cue.ValueAttr | cue.FieldAttr, path: "c4", out: "[]", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.path, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).LookupPath(cue.ParsePath(tc.path)) a := v.Attributes(tc.flags) got := fmt.Sprint(a) if got != tc.out { t.Errorf("got %v; want %v", got, tc.out) } }) } } func TestAttributeErr(t *testing.T) { const config = ` a: { a: 0 @foo(a,b,c=1) b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) } ` testCases := []struct { path string attr string err error }{{ path: "a", attr: "foo", err: nil, }, { path: "a", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }, { path: "xx", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }, { path: "e", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.path+"-"+tc.attr, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a", tc.path) a := v.Attribute(tc.attr) err := a.Err() if !cmpError(err, tc.err) { t.Errorf("got %v; want %v", err, tc.err) } }) } } func TestAttributeName(t *testing.T) { const config = ` a: 0 @foo(a,b,c=1) @bar() ` cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a") a := v.Attribute("foo") if got, want := a.Name(), "foo"; got != want { t.Errorf("got %v; want %v", got, want) } }) } func TestAttributeString(t *testing.T) { const config = ` a: { a: 0 @foo(a,b,c=1) b: 1 @bar(a,b,c,d=1) @foo(a,,d=1,e="x y","f g") } ` testCases := []struct { path string attr string pos int str string err error }{{ path: "a", attr: "foo", pos: 0, str: "a", }, { path: "a", attr: "foo", pos: 2, str: "c=1", }, { path: "b", attr: "bar", pos: 3, str: "d=1", }, { path: "b", attr: "foo", pos: 3, str: `e="x y"`, }, { path: "b", attr: "foo", pos: 4, str: `f g`, }, { path: "e", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }, { path: "b", attr: "foo", pos: 5, err: errors.New("field does not exist"), }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a", tc.path) a := v.Attribute(tc.attr) got, err := a.String(tc.pos) if !cmpError(err, tc.err) { t.Errorf("err: got %v; want %v", err, tc.err) } if got != tc.str { t.Errorf("str: got %v; want %v", got, tc.str) } }) } } func TestAttributeArg(t *testing.T) { const config = ` a: 1 @foo(a,,d=1,e="x y","f g", with spaces , s= spaces in value ) ` testCases := []struct { pos int key string val string raw string }{{ pos: 0, key: "a", val: "", raw: "a", }, { pos: 1, key: "", val: "", raw: "", }, { pos: 2, key: "d", val: "1", raw: "d=1", }, { pos: 3, key: "e", val: "x y", raw: `e="x y"`, }, { pos: 4, key: "f g", val: "", raw: `"f g"`, }, { pos: 5, key: "with spaces", val: "", raw: " with spaces ", }, { pos: 6, key: "s", val: "spaces in value", raw: " s= spaces in value ", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%d", tc.pos), func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a") a := v.Attribute("foo") key, val := a.Arg(tc.pos) raw := a.RawArg(tc.pos) if got, want := key, tc.key; got != want { t.Errorf("unexpected key; got %q want %q", got, want) } if got, want := val, tc.val; got != want { t.Errorf("unexpected value; got %q want %q", got, want) } if got, want := raw, tc.raw; got != want { t.Errorf("unexpected raw value; got %q want %q", got, want) } }) } } func TestAttributeInt(t *testing.T) { const config = ` a: { a: 0 @foo(1,3,c=1) b: 1 @bar(a,-4,c,d=1) @foo(a,,d=1) c: 2 @nongo(10Mi) } ` testCases := []struct { path string attr string pos int val int64 err error }{{ path: "a", attr: "foo", pos: 0, val: 1, }, { path: "b", attr: "bar", pos: 1, val: -4, }, { path: "e", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }, { path: "b", attr: "foo", pos: 4, err: errors.New("field does not exist"), }, { path: "a", attr: "foo", pos: 2, err: errors.New(`illegal number start "c=1"`), }, { path: "c", attr: "nongo", pos: 0, val: 10 << 20, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a", tc.path) a := v.Attribute(tc.attr) got, err := a.Int(tc.pos) if !cmpError(err, tc.err) { t.Errorf("err: got %v; want %v", err, tc.err) } if got != tc.val { t.Errorf("val: got %v; want %v", got, tc.val) } }) } } func TestAttributeFlag(t *testing.T) { const config = ` a: { a: 0 @foo(a,b,c=1) b: 1 @bar(a,b,c,d=1) @foo(a,,d=1) } ` testCases := []struct { path string attr string pos int flag string val bool err error }{{ path: "a", attr: "foo", pos: 0, flag: "a", val: true, }, { path: "b", attr: "bar", pos: 1, flag: "a", val: false, }, { path: "b", attr: "bar", pos: 0, flag: "c", val: true, }, { path: "e", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }, { path: "b", attr: "foo", pos: 4, err: errors.New("field does not exist"), }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a", tc.path) a := v.Attribute(tc.attr) got, err := a.Flag(tc.pos, tc.flag) if !cmpError(err, tc.err) { t.Errorf("err: got %v; want %v", err, tc.err) } if got != tc.val { t.Errorf("val: got %v; want %v", got, tc.val) } }) } } func TestAttributeLookup(t *testing.T) { const config = ` a: { a: 0 @foo(a,b,c=1) b: 1 @bar(a,b,e =-5,d=1) @foo(a,,d=1) } ` testCases := []struct { path string attr string pos int key string val string err error }{{ path: "a", attr: "foo", pos: 0, key: "c", val: "1", }, { path: "b", attr: "bar", pos: 1, key: "a", val: "", }, { path: "b", attr: "bar", pos: 0, key: "e", val: "-5", }, { path: "b", attr: "bar", pos: 0, key: "d", val: "1", }, { path: "b", attr: "foo", pos: 2, key: "d", val: "1", }, { path: "b", attr: "foo", pos: 2, key: "f", val: "", }, { path: "e", attr: "bar", err: errors.New(`attribute "bar" does not exist`), }, { path: "b", attr: "foo", pos: 4, err: errors.New("field does not exist"), }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T, m *cuetdtest.M) { v := getValue(m, config).Lookup("a", tc.path) a := v.Attribute(tc.attr) got, _, err := a.Lookup(tc.pos, tc.key) if !cmpError(err, tc.err) { t.Errorf("err: got %v; want %v", err, tc.err) } if got != tc.val { t.Errorf("val: got %v; want %v", got, tc.val) } }) } } cue-lang-cue-db9cc73/cue/bench_test.go000066400000000000000000000073121474664451600177240ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "bytes" "fmt" "io/fs" "os" "path/filepath" "testing" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/internal/core/eval" "cuelang.org/go/internal/core/runtime" "cuelang.org/go/internal/cuetdtest" "cuelang.org/go/internal/cuetest" "cuelang.org/go/internal/cuetxtar" "golang.org/x/tools/txtar" ) var ( matrix = cuetdtest.FullMatrix ) func Benchmark(b *testing.B) { root := "testdata/benchmarks" err := filepath.WalkDir(root, func(fullpath string, entry fs.DirEntry, err error) error { if err != nil { return err } if entry.IsDir() || filepath.Ext(fullpath) != ".txtar" { return nil } a, err := txtar.ParseFile(fullpath) if err != nil { return err } inst := cuetxtar.Load(a, b.TempDir())[0] if inst.Err != nil { return inst.Err } r := runtime.New() v, err := r.Build(nil, inst) if err != nil { b.Fatal(err) } e := eval.New(r) ctx := e.NewContext(v) v.Finalize(ctx) if cuetest.UpdateGoldenFiles { const statsFile = "stats.txt" var stats txtar.File var statsPos int for i, f := range a.Files { if f.Name == statsFile { stats = f statsPos = i break } } if stats.Name == "" { // At stats.txt as the first file. a.Files = append([]txtar.File{{ Name: statsFile, }}, a.Files...) } a.Files[statsPos].Data = []byte(ctx.Stats().String() + "\n\n") info, err := entry.Info() if err != nil { b.Fatal(err) } os.WriteFile(fullpath, txtar.Format(a), info.Mode()) } b.Run(entry.Name(), func(b *testing.B) { for _, m := range matrix { b.Run(m.Name(), func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { ctx := m.CueContext() value := ctx.BuildInstance(cuetxtar.Load(a, b.TempDir())[0]) value.Validate() } }) } }) return nil }) if err != nil { b.Fatal(err) } } // TODO(mvdan): move this benchmark to internal/encoding // and cover other encodings too. // We should also cover both encoding and decoding performance. func BenchmarkLargeValueMarshalJSON(b *testing.B) { b.ReportAllocs() size := 2000 var buf bytes.Buffer fmt.Fprintf(&buf, "longString: \"") for range size { fmt.Fprintf(&buf, "x") } fmt.Fprintf(&buf, "\"\n") fmt.Fprintf(&buf, "nestedList: ") for range size { fmt.Fprintf(&buf, "[") } fmt.Fprintf(&buf, "0") for range size { fmt.Fprintf(&buf, "]") } fmt.Fprintf(&buf, "\n") fmt.Fprintf(&buf, "longList: [") for i := range size { if i > 0 { fmt.Fprintf(&buf, ",") } fmt.Fprintf(&buf, "0") } fmt.Fprintf(&buf, "]\n") fmt.Fprintf(&buf, "nestedStruct: ") for range size { fmt.Fprintf(&buf, "{k:") } fmt.Fprintf(&buf, "0") for range size { fmt.Fprintf(&buf, "}") } fmt.Fprintf(&buf, "\n") fmt.Fprintf(&buf, "longStruct: {") for i := range size { if i > 0 { fmt.Fprintf(&buf, ",") } fmt.Fprintf(&buf, "k%d: 0", i) } fmt.Fprintf(&buf, "}\n") ctx := cuecontext.New() val := ctx.CompileBytes(buf.Bytes()) if err := val.Err(); err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { data, err := val.MarshalJSON() if err != nil { b.Fatal(err) } _ = data } } cue-lang-cue-db9cc73/cue/build.go000066400000000000000000000120151474664451600167010ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/runtime" ) // A Runtime is used for creating CUE Values. // // Any operation that involves two Values or Instances should originate from // the same Runtime. // // The zero value of Runtime works for legacy reasons, but // should not be used. It may panic at some point. // // Deprecated: use [Context]. type Runtime runtime.Runtime func (r *Runtime) runtime() *runtime.Runtime { rt := (*runtime.Runtime)(r) rt.Init() return rt } type hiddenRuntime = Runtime func (r *Runtime) complete(p *build.Instance, v *adt.Vertex) (*Instance, error) { idx := r.runtime() inst := getImportFromBuild(idx, p, v) inst.ImportPath = p.ImportPath if inst.Err != nil { return nil, inst.Err } return inst, nil } // Compile compiles the given source into an Instance. The source code may be // provided as a string, byte slice, io.Reader. The name is used as the file // name in position information. The source may import builtin packages. Use // Build to allow importing non-builtin packages. // // Deprecated: use [Context] with methods like [Context.CompileString] or [Context.CompileBytes]. // The use of [Instance] is being phased out. func (r *hiddenRuntime) Compile(filename string, source interface{}) (*Instance, error) { cfg := &runtime.Config{Filename: filename} v, p := r.runtime().Compile(cfg, source) return r.complete(p, v) } // CompileFile compiles the given source file into an Instance. The source may // import builtin packages. Use Build to allow importing non-builtin packages. // // Deprecated: use [Context.BuildFile]. The use of [Instance] is being phased out. func (r *hiddenRuntime) CompileFile(file *ast.File) (*Instance, error) { v, p := r.runtime().CompileFile(nil, file) return r.complete(p, v) } // CompileExpr compiles the given source expression into an Instance. The source // may import builtin packages. Use Build to allow importing non-builtin // packages. // // Deprecated: use [Context.BuildExpr]. The use of [Instance] is being phased out. func (r *hiddenRuntime) CompileExpr(expr ast.Expr) (*Instance, error) { f, err := astutil.ToFile(expr) if err != nil { return nil, err } runtime := r.runtime() v := (*Context)(runtime).BuildExpr(expr) err = v.Err() inst := &Instance{ index: runtime, root: v.v, inst: &build.Instance{ Files: []*ast.File{f}, }, Err: errors.Promote(err, ""), Incomplete: err != nil, } return inst, err } // Parse parses a CUE source value into a CUE Instance. The source code may be // provided as a string, byte slice, or io.Reader. The name is used as the file // name in position information. The source may import builtin packages. // // Deprecated: use [Context.CompileString] or [Context.CompileBytes]. // The use of [Instance] is being phased out. func (r *hiddenRuntime) Parse(name string, source interface{}) (*Instance, error) { return r.Compile(name, source) } // Build creates an Instance from the given build.Instance. A returned Instance // may be incomplete, in which case its Err field is set. // // Deprecated: use [Context.BuildInstance]. The use of [Instance] is being phased out. func (r *hiddenRuntime) Build(p *build.Instance) (*Instance, error) { v, _ := r.runtime().Build(nil, p) return r.complete(p, v) } // Deprecated: use [Context.BuildInstances]. The use of [Instance] is being phased out. func Build(instances []*build.Instance) []*Instance { if len(instances) == 0 { panic("cue: list of instances must not be empty") } var r Runtime a, _ := r.BuildInstances(instances) return a } // Deprecated: use [Context.BuildInstances]. The use of [Instance] is being phased out. func (r *hiddenRuntime) BuildInstances(instances []*build.Instance) ([]*Instance, error) { index := r.runtime() loaded := []*Instance{} var errs errors.Error for _, p := range instances { v, _ := index.Build(nil, p) i := getImportFromBuild(index, p, v) errs = errors.Append(errs, i.Err) loaded = append(loaded, i) } // TODO: insert imports return loaded, errs } // FromExpr creates an instance from an expression. // Any references must be resolved beforehand. // // Deprecated: use [Context.BuildExpr]. The use of [Instance] is being phased out. func (r *hiddenRuntime) FromExpr(expr ast.Expr) (*Instance, error) { return r.CompileFile(&ast.File{ Decls: []ast.Decl{&ast.EmbedDecl{Expr: expr}}, }) } cue-lang-cue-db9cc73/cue/build/000077500000000000000000000000001474664451600163535ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/build/context.go000066400000000000000000000063511474664451600203730ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package build defines data types and utilities for defining CUE configuration // instances. // // This package enforces the rules regarding packages and instances as defined // in the spec, but it leaves any other details, as well as handling of modules, // up to the implementation. // // A full implementation of instance loading can be found in the loader package. // // WARNING: this packages may change. It is fine to use load and cue, who both // use this package. package build import ( "cuelang.org/go/cue/ast" ) // A Context keeps track of state of building instances and caches work. type Context struct { loader LoadFunc parseFunc func(str string, src interface{}) (*ast.File, error) initialized bool imports map[string]*Instance } // NewInstance creates an instance for this Context. func (c *Context) NewInstance(dir string, f LoadFunc) *Instance { if c == nil { c = &Context{} } if f == nil { f = c.loader } return &Instance{ ctxt: c, loadFunc: f, Dir: dir, } } // Complete finishes the initialization of an instance. All files must have // been added with AddFile before this call. func (inst *Instance) Complete() error { if inst.done { return inst.Err } inst.done = true err := inst.complete() if err != nil { inst.ReportError(err) } if inst.Err != nil { inst.Incomplete = true return inst.Err } return nil } func (c *Context) init() { if !c.initialized { c.initialized = true c.imports = map[string]*Instance{} } } // Options: // - certain parse modes // - parallelism // - error handler (allows cancelling the context) // - file set. // NewContext creates a new build context. // // All instances must be created with a context. func NewContext(opts ...Option) *Context { c := &Context{} for _, o := range opts { o(c) } c.init() return c } // Option define build options. type Option func(c *Context) // Loader sets parsing options. func Loader(f LoadFunc) Option { return func(c *Context) { c.loader = f } } // ParseFile is called to read and parse each file // when building syntax tree. // It must be safe to call ParseFile simultaneously from multiple goroutines. // If f is nil, the loader will use [cuelang.org/go/cue/parser.ParseFile]. // // ParseFile should parse the source from src and use filename only for // recording position information. // // An application may supply a custom implementation of ParseFile // to change the effective file contents or the behavior of the parser, // or to modify the syntax tree. For example, changing the backwards // compatibility. func ParseFile(f func(filename string, src interface{}) (*ast.File, error)) Option { return func(c *Context) { c.parseFunc = f } } cue-lang-cue-db9cc73/cue/build/doc.go000066400000000000000000000012471474664451600174530ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package build defines collections of CUE files to build an instance. package build cue-lang-cue-db9cc73/cue/build/file.go000066400000000000000000000063611474664451600176270ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package build import "cuelang.org/go/cue/errors" // Note: the json tags in File correspond directly to names // used in the encoding/filetypes package, which unmarshals // results from CUE into a build.File. // A File represents a file that is part of the build process. type File struct { Filename string `json:"filename"` Encoding Encoding `json:"encoding,omitempty"` Interpretation Interpretation `json:"interpretation,omitempty"` Form Form `json:"form,omitempty"` // Tags holds key-value pairs relating to the encoding // conventions to use for the file. Tags map[string]string `json:"tags,omitempty"` // e.g. code+lang=go // BoolTags holds boolean-valued tags relating to the // encoding conventions to use for the file. BoolTags map[string]bool `json:"boolTags,omitempty"` ExcludeReason errors.Error `json:"-"` Source interface{} `json:"-"` // TODO: swap out with concrete type. } // A Encoding indicates a file format for representing a program. type Encoding string const ( CUE Encoding = "cue" JSON Encoding = "json" YAML Encoding = "yaml" TOML Encoding = "toml" JSONL Encoding = "jsonl" Text Encoding = "text" Binary Encoding = "binary" Protobuf Encoding = "proto" TextProto Encoding = "textproto" BinaryProto Encoding = "pb" Code Encoding = "code" // Programming languages ) // An Interpretation determines how a certain program should be interpreted. // For instance, data may be interpreted as describing a schema, which itself // can be converted to a CUE schema. type Interpretation string const ( // Auto interprets the underlying data file as data, JSON Schema or OpenAPI, // depending on the existence of certain marker fields. // // JSON Schema is identified by a top-level "$schema" field with a URL // of the form "https?://json-schema.org/.*schema#?". // // OpenAPI is identified by the existence of a top-level field "openapi" // with a major semantic version of 3, as well as the existence of // the info.title and info.version fields. // // In all other cases, the underlying data is interpreted as is. Auto Interpretation = "auto" JSONSchema Interpretation = "jsonschema" OpenAPI Interpretation = "openapi" ProtobufJSON Interpretation = "pb" ) // A Form specifies the form in which a program should be represented. type Form string const ( Full Form = "full" Schema Form = "schema" Struct Form = "struct" Final Form = "final" // picking default values, may be non-concrete Graph Form = "graph" // Data only, but allow references DAG Form = "dag" // Like graph, but don't allow cycles Data Form = "data" // always final ) cue-lang-cue-db9cc73/cue/build/import.go000066400000000000000000000076331474664451600202250ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package build import ( "slices" "strconv" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" ) type LoadFunc func(pos token.Pos, path string) *Instance type cueError = errors.Error type buildError struct { cueError inputs []token.Pos } func (e *buildError) InputPositions() []token.Pos { return e.inputs } func (inst *Instance) complete() errors.Error { // TODO: handle case-insensitive collisions. // dir := inst.Dir // names := []string{} // for _, src := range sources { // names = append(names, src.path) // } // f1, f2 := str.FoldDup(names) // if f1 != "" { // return nil, fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2) // } var ( c = inst.ctxt imported = map[string][]token.Pos{} ) for _, f := range inst.Files { for _, spec := range f.Imports { quoted := spec.Path.Value path, err := strconv.Unquote(quoted) if err != nil { inst.Err = errors.Append(inst.Err, errors.Newf( spec.Path.Pos(), "%s: parser returned invalid quoted string: <%s>", f.Filename, quoted)) } imported[path] = append(imported[path], spec.Pos()) } } paths := make([]string, 0, len(imported)) for path := range imported { paths = append(paths, path) if path == "" { return &buildError{ errors.Newf(token.NoPos, "empty import path"), imported[path], } } } slices.Sort(paths) if inst.loadFunc != nil { for i, path := range paths { // isLocal := IsLocalImport(path) // if isLocal { // path = dirToImportPath(filepath.Join(dir, path)) // } imp := c.imports[path] if imp == nil { pos := token.NoPos if len(imported[path]) > 0 { pos = imported[path][0] } imp = inst.loadFunc(pos, path) if imp == nil { continue } if imp.Err != nil { return errors.Wrapf(imp.Err, pos, "import failed") } imp.ImportPath = path // imp.parent = inst c.imports[path] = imp // imp.parent = nil } else if imp.parent != nil { // TODO: report a standard cycle message. // cycle is now handled explicitly in loader } paths[i] = imp.ImportPath inst.addImport(imp) if imp.Incomplete { inst.Incomplete = true } } } inst.ImportPaths = paths inst.ImportPos = imported // Build full dependencies deps := make(map[string]*Instance) var q []*Instance q = append(q, inst.Imports...) for i := 0; i < len(q); i++ { p1 := q[i] path := p1.ImportPath // The same import path could produce an error or not, // depending on what tries to import it. // Prefer to record entries with errors, so we can report them. // p0 := deps[path] // if err0, err1 := lastError(p0), lastError(p1); p0 == nil || err1 != nil && (err0 == nil || len(err0.ImportStack) > len(err1.ImportStack)) { // deps[path] = p1 // for _, p2 := range p1.Imports { // if deps[p2.ImportPath] != p2 { // q = append(q, p2) // } // } // } if _, ok := deps[path]; !ok { deps[path] = p1 } } inst.Deps = make([]string, 0, len(deps)) for dep := range deps { inst.Deps = append(inst.Deps, dep) } slices.Sort(inst.Deps) for _, dep := range inst.Deps { p1 := deps[dep] if p1 == nil { panic("impossible: missing entry in package cache for " + dep + " imported by " + inst.ImportPath) } if p1.Err != nil { inst.DepsErrors = append(inst.DepsErrors, p1.Err) } } return nil } cue-lang-cue-db9cc73/cue/build/instance.go000066400000000000000000000211451474664451600205110ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package build import ( "fmt" pathpkg "path" "path/filepath" "strings" "unicode" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" ) // An Instance describes the collection of files, and its imports, necessary // to build a CUE instance. // // A typical way to create an Instance is to use the cue/load package. type Instance struct { ctxt *Context BuildFiles []*File // files to be included in the build IgnoredFiles []*File // files excluded for this build OrphanedFiles []*File // recognized file formats not part of any build InvalidFiles []*File // could not parse these files UnknownFiles []*File // unknown file types User bool // True if package was created from individual files. // Files contains the AST for all files part of this instance. // TODO: the intent is to deprecate this in favor of BuildFiles. Files []*ast.File loadFunc LoadFunc done bool // PkgName is the name specified in the package clause. PkgName string hasName bool // ImportPath returns the unique path to identify an imported instance. // // Instances created with [Context.NewInstance] do not have an import path. ImportPath string // Imports lists the instances of all direct imports of this instance. Imports []*Instance // The Err for loading this package or nil on success. This does not // include any errors of dependencies. Incomplete will be set if there // were any errors in dependencies. Err errors.Error parent *Instance // TODO: for cycle detection // The following fields are for informative purposes and are not used by // the cue package to create an instance. // DisplayPath is a user-friendly version of the package or import path. DisplayPath string // Module defines the module name of a package. It must be defined if // the packages within the directory structure of the module are to be // imported by other packages, including those within the module. Module string // Root is the root of the directory hierarchy, it may be "" if this an // instance has no imports. // If Module != "", this corresponds to the module root. // Root/pkg is the directory that holds third-party packages. Root string // Dir is the package directory. A package may also include files from // ancestor directories, up to the module file. Dir string // NOTICE: the below struct field tags may change in the future. // Incomplete reports whether any dependencies had an error. Incomplete bool `api:"alpha"` // Dependencies // ImportPaths gives the transitive dependencies of all imports. ImportPaths []string `api:"alpha"` ImportPos map[string][]token.Pos `api:"alpha"` // line information for Imports Deps []string `api:"alpha"` DepsErrors []error `api:"alpha"` Match []string `api:"alpha"` } // RelPath reports the path of f relative to the root of the instance's module // directory. The full path is returned if a relative path could not be found. func (inst *Instance) RelPath(f *File) string { p, err := filepath.Rel(inst.Root, f.Filename) if err != nil { return f.Filename } return p } // ID returns the package ID unique for this module. func (inst *Instance) ID() string { if s := inst.ImportPath; s != "" { return s } if inst.PkgName == "" { return "_" } s := fmt.Sprintf("%s:%s", inst.Module, inst.PkgName) return s } // Dependencies reports all Instances on which this instance depends. func (inst *Instance) Dependencies() []*Instance { // TODO: as cyclic dependencies are not allowed, we could just not check. // Do for safety now and remove later if needed. return appendDependencies(nil, inst, map[*Instance]bool{}) } func appendDependencies(a []*Instance, inst *Instance, done map[*Instance]bool) []*Instance { for _, d := range inst.Imports { if done[d] { continue } a = append(a, d) done[d] = true a = appendDependencies(a, d, done) } return a } // Abs converts relative path used in the one of the file fields to an // absolute one. func (inst *Instance) Abs(path string) string { if filepath.IsAbs(path) { return path } return filepath.Join(inst.Root, path) } func (inst *Instance) setPkg(pkg string) bool { if !inst.hasName { inst.hasName = true inst.PkgName = pkg return true } return false } // ReportError reports an error processing this instance. func (inst *Instance) ReportError(err errors.Error) { inst.Err = errors.Append(inst.Err, err) } // Context defines the build context for this instance. All files defined // in Syntax as well as all imported instances must be created using the // same build context. func (inst *Instance) Context() *Context { return inst.ctxt } func (inst *Instance) parse(name string, src interface{}) (*ast.File, error) { if inst.ctxt != nil && inst.ctxt.parseFunc != nil { return inst.ctxt.parseFunc(name, src) } return parser.ParseFile(name, src, parser.ParseComments) } // LookupImport defines a mapping from an ImportSpec's ImportPath to Instance. func (inst *Instance) LookupImport(path string) *Instance { path = inst.expandPath(path) for _, inst := range inst.Imports { if inst.ImportPath == path { return inst } } return nil } func (inst *Instance) addImport(imp *Instance) { for _, inst := range inst.Imports { if inst.ImportPath == imp.ImportPath { if inst != imp { panic("import added multiple times with different instances") } return } } inst.Imports = append(inst.Imports, imp) } // AddFile adds the file with the given name to the list of files for this // instance. The file may be loaded from the cache of the instance's context. // It does not process the file's imports. The package name of the file must // match the package name of the instance. // // Deprecated: use [Instance.AddSyntax] or wait for this to be renamed using a new // signature. func (inst *Instance) AddFile(filename string, src interface{}) error { file, err := inst.parse(filename, src) if err != nil { // should always be an errors.List, but just in case. err := errors.Promote(err, "error adding file") inst.ReportError(err) return err } return inst.AddSyntax(file) } // AddSyntax adds the given file to list of files for this instance. The package // name of the file must match the package name of the instance. func (inst *Instance) AddSyntax(file *ast.File) errors.Error { astutil.Resolve(file, func(pos token.Pos, msg string, args ...interface{}) { inst.Err = errors.Append(inst.Err, errors.Newf(pos, msg, args...)) }) pkg := file.PackageName() if pkg != "" && pkg != "_" && !inst.User && !inst.setPkg(pkg) && pkg != inst.PkgName { err := errors.Newf(file.Pos(), "package name %q conflicts with previous package name %q", pkg, inst.PkgName) inst.ReportError(err) return err } inst.Files = append(inst.Files, file) return nil } func (inst *Instance) expandPath(path string) string { isLocal := IsLocalImport(path) if isLocal { path = dirToImportPath(filepath.Join(inst.Dir, path)) } return path } // dirToImportPath returns the pseudo-import path we use for a package // outside the CUE path. It begins with _/ and then contains the full path // to the directory. If the package lives in c:\home\gopher\my\pkg then // the pseudo-import path is _/c_/home/gopher/my/pkg. // Using a pseudo-import path like this makes the ./ imports no longer // a special case, so that all the code to deal with ordinary imports works // automatically. func dirToImportPath(dir string) string { return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir))) } func makeImportValid(r rune) rune { // Should match Go spec, compilers, and ../../go/parser/parser.go:/isValidImport. const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) { return '_' } return r } // IsLocalImport reports whether the import path is // a local import path, like ".", "..", "./foo", or "../foo". func IsLocalImport(path string) bool { return path == "." || path == ".." || strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../") } cue-lang-cue-db9cc73/cue/build_test.go000066400000000000000000000120011474664451600177330ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/token" "cuelang.org/go/internal/core/debug" "cuelang.org/go/internal/value" ) func TestFromExpr(t *testing.T) { testCases := []struct { expr ast.Expr out string }{{ expr: ast.NewString("Hello"), out: `"Hello"`, }, { expr: ast.NewList( ast.NewString("Hello"), ast.NewString("World"), ), out: `["Hello", "World"]`, }} for _, tc := range testCases { t.Run("", func(t *testing.T) { r := cuecontext.New() v := r.BuildExpr(tc.expr) if err := v.Err(); err != nil { t.Fatal(err) } if got := fmt.Sprint(v); got != tc.out { t.Errorf("\n got: %v; want %v", got, tc.out) } }) } } func TestBuild(t *testing.T) { files := func(s ...string) []string { return s } insts := func(i ...*bimport) []*bimport { return i } pkg1 := &bimport{ "pkg1", files(` package pkg1 Object: "World" `), } pkg2 := &bimport{ "mod.test/foo/pkg2:pkg", files(` package pkg Number: 12 `), } pkg3 := &bimport{ "mod.test/foo/v1:pkg3", files(` package pkg3 List: [1,2,3] `), } testCases := []struct { instances []*bimport emit string }{{ insts(&bimport{"", files(`test: "ok"`)}), `{test:"ok"}`, }, { insts(&bimport{"", files( `package test import "math" "Pi: \(math.Pi)!"`)}), `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`, }, { insts(&bimport{"", files( `package test import math2 "math" "Pi: \(math2.Pi)!"`)}), `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`, }, { insts(pkg1, &bimport{"", files( `package test import "pkg1" "Hello \(pkg1.Object)!"`), }), `"Hello World!"`, }, { insts(pkg1, &bimport{"", files( `package test import "pkg1" "Hello \(pkg1.Object)!"`), }), `"Hello World!"`, }, { insts(pkg1, &bimport{"", files( `package test import pkg2 "pkg1" #pkg1: pkg2.Object "Hello \(#pkg1)!"`), }), `"Hello World!"`, }, { insts(pkg1, pkg2, &bimport{"", files( `package test import bar "pkg1" import baz "mod.test/foo/pkg2:pkg" pkg1: Object: 3 "Hello \(pkg1.Object)!"`), }), `imported and not used: "pkg1" as bar (and 1 more errors)`, }, { insts(pkg2, &bimport{"", files( `package test import "mod.test/foo/pkg2:pkg" "Hello \(pkg2.Number)!"`), }), `imported and not used: "mod.test/foo/pkg2:pkg" (and 1 more errors)`, // `file0.cue:5:14: unresolved reference pkg2`, }, { insts(pkg2, &bimport{"", files( `package test import "mod.test/foo/pkg2:pkg" "Hello \(pkg.Number)!"`), }), `"Hello 12!"`, }, { insts(pkg3, &bimport{"", files( `package test import "mod.test/foo/v1:pkg3" "Hello \(pkg3.List[1])!"`), }), `"Hello 2!"`, }, { insts(pkg3, &bimport{"", files( `package test import "mod.test/foo/v1:pkg3" pkg3: 3 "Hello \(pkg3.List[1])!"`), }), `pkg3 redeclared as imported package name previous declaration at file0.cue:5:5`, }} for _, tc := range testCases { t.Run("", func(t *testing.T) { insts := cue.Build(makeInstances(tc.instances)) var got string if err := insts[0].Err; err != nil { got = err.Error() } else { cfg := &debug.Config{Compact: true} r, v := value.ToInternal(insts[0].Value()) got = debug.NodeString(r, v, cfg) } if got != tc.emit { t.Errorf("\n got: %s\nwant: %s", got, tc.emit) } }) } } type builder struct { ctxt *build.Context imports map[string]*bimport } func (b *builder) load(pos token.Pos, path string) *build.Instance { bi := b.imports[path] if bi == nil { return nil } return b.build(bi) } type bimport struct { path string // "" means top-level files []string } func makeInstances(insts []*bimport) (instances []*build.Instance) { b := builder{ ctxt: build.NewContext(), imports: map[string]*bimport{}, } for _, bi := range insts { if bi.path != "" { b.imports[bi.path] = bi } } for _, bi := range insts { if bi.path == "" { instances = append(instances, b.build(bi)) } } return } func (b *builder) build(bi *bimport) *build.Instance { path := bi.path if path == "" { path = "dir" } p := b.ctxt.NewInstance(path, b.load) for i, f := range bi.files { _ = p.AddFile(fmt.Sprintf("file%d.cue", i), f) } _ = p.Complete() return p } cue-lang-cue-db9cc73/cue/builtin.go000066400000000000000000000014561474664451600172570ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cuelang.org/go/cue/token" "cuelang.org/go/internal/core/adt" ) func pos(n adt.Node) (p token.Pos) { if n == nil { return } src := n.Source() if src == nil { return } return src.Pos() } cue-lang-cue-db9cc73/cue/builtin_test.go000066400000000000000000000114231474664451600203110ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "testing" "cuelang.org/go/cue" _ "cuelang.org/go/pkg" ) func TestBuiltins(t *testing.T) { test := func(pkg, expr string) []*bimport { return []*bimport{{"", []string{fmt.Sprintf("import %q\n(%s)", pkg, expr)}, }} } testExpr := func(expr string) []*bimport { return []*bimport{{"", []string{fmt.Sprintf("(%s)", expr)}, }} } testCases := []struct { instances []*bimport emit string }{{ test("math", "math.Pi"), `3.14159265358979323846264338327950288419716939937510582097494459`, }, { test("math", "math.Floor(math.Pi)"), `3`, }, { test("math", "math.Pi(3)"), `_|_ // cannot call non-function math.Pi (type float)`, }, { test("math", "math.Floor(3, 5)"), `_|_ // too many arguments in call to math.Floor (have 2, want 1)`, }, { test("math", `math.Floor("foo")`), `_|_ // cannot use "foo" (type string) as number in argument 1 to math.Floor`, }, { test("crypto/sha256", `sha256.Sum256("hash me")`), `'\xeb \x1a\xf5\xaa\xf0\xd6\x06)\xd3Ҧ\x1eFl\xfc\x0f\xed\xb5\x17\xad\xd81\xec\xacR5\xe1کc\xd6'`, }, { test("crypto/md5", `len(md5.Sum("hash me"))`), `16`, }, { test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<3})`), `_|_ // error in call to encoding/yaml.Validate: a: invalid value 4 (out of bound <3)`, }, { test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<5})`), `true`, }, { test("encoding/yaml", `yaml.Validate("a: 2\n", {a:<5, b:int})`), `_|_ // error in call to encoding/yaml.Validate: b: incomplete value int`, }, { test("strconv", `strconv.FormatUint(64, 16)`), `"40"`, }, { test("regexp", `regexp.Find(#"f\w\w"#, "afoot")`), `"foo"`, }, { test("regexp", `regexp.Find(#"f\w\w"#, "bar")`), `_|_ // error in call to regexp.Find: no match`, }, { testExpr(`len([1, 2, 3])`), `3`, }, { testExpr(`len("foo")`), `3`, }, { test("encoding/json", `json.MarshalStream([{a: 1}, {b: 2}])`), `"""` + "\n\t{\"a\":1}\n\t{\"b\":2}\n\n\t" + `"""`, }, { test("encoding/json", `{ x: int y: json.Marshal({a: x}) }`), `{ x: int y: _|_ // cannot convert incomplete value "int" to JSON }`, }, { test("encoding/yaml", `yaml.MarshalStream([{a: 1}, {b: 2}])`), `"""` + "\n\ta: 1\n\t---\n\tb: 2\n\n\t" + `"""`, }, { test("struct", `struct.MinFields(0) & ""`), `_|_ // conflicting values struct.MinFields(0) and "" (mismatched types struct and string)`, }, { test("struct", `struct.MinFields(0) & {a: 1}`), `{ a: 1 }`, }, { test("struct", `struct.MinFields(2) & {a: 1}`), // TODO: original value may be better. // `_|_ // invalid value {a:1} (does not satisfy struct.MinFields(2))`, `_|_ // invalid value {a:1} (does not satisfy struct.MinFields(2)): len(fields) < MinFields(2) (1 < 2)`, }, { test("time", `time.Time & "1937-01-01T12:00:27.87+00:20"`), `"1937-01-01T12:00:27.87+00:20"`, }, { test("time", `time.Time & "no time"`), `_|_ // invalid value "no time" (does not satisfy time.Time): error in call to time.Time: invalid time "no time"`, }, { test("time", `time.Unix(1500000000, 123456)`), `"2017-07-14T02:40:00.000123456Z"`, }} for i, tc := range testCases { t.Run(fmt.Sprint(i), func(t *testing.T) { insts := cue.Build(makeInstances(tc.instances)) if err := insts[0].Err; err != nil { t.Fatal(err) } v := insts[0].Value() got := fmt.Sprintf("%+v", v) if got != tc.emit { t.Errorf("\n got: %q\nwant: %q", got, tc.emit) } }) } } // For debugging purposes. Do not remove. func TestSingleBuiltin(t *testing.T) { t.Skip("error message") test := func(pkg, expr string) []*bimport { return []*bimport{{"", []string{fmt.Sprintf("import %q\n(%s)", pkg, expr)}, }} } testCases := []struct { instances []*bimport emit string }{{ test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`), `_|_ // error in call to list.Sort: less: invalid operands {b:2} and {a:1} to '<' (type struct and struct)`, }} for i, tc := range testCases { t.Run(fmt.Sprint(i), func(t *testing.T) { insts := cue.Build(makeInstances(tc.instances)) if err := insts[0].Err; err != nil { t.Fatal(err) } v := insts[0].Value() got := fmt.Sprint(v) if got != tc.emit { t.Errorf("\n got: %s\nwant: %s", got, tc.emit) } }) } } cue-lang-cue-db9cc73/cue/context.go000066400000000000000000000360211474664451600172710ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cmp" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/compile" "cuelang.org/go/internal/core/convert" "cuelang.org/go/internal/core/debug" "cuelang.org/go/internal/core/eval" "cuelang.org/go/internal/core/runtime" ) // A Context is used for creating CUE [Value]s. // // A Context keeps track of loaded instances, indices of internal // representations of values, and defines the set of supported builtins. Any // operation that involves two Values should originate from the same Context. // // Use [cuelang.org/go/cue/cuecontext.New] to create a new context. type Context runtime.Runtime func (c *Context) runtime() *runtime.Runtime { rt := (*runtime.Runtime)(c) if !rt.IsInitialized() { panic("cue: uninitialized Context: use cuecontext.New instead of zero value") } return rt } func (c *Context) ctx() *adt.OpContext { return newContext(c.runtime()) } // Context reports the Context with which this value was created. func (v Value) Context() *Context { return (*Context)(v.idx) } // A BuildOption defines options for the various build-related methods of // Context. type BuildOption func(o *runtime.Config) // Scope defines a context in which to resolve unresolved identifiers. // // Only one scope may be given. It panics if more than one scope is given // or if the Context in which scope was created differs from the one where // this option is used. func Scope(scope Value) BuildOption { return func(o *runtime.Config) { if o.Runtime != scope.idx { panic("incompatible runtime") } if o.Scope != nil { panic("more than one scope is given") } o.Scope = valueScope(scope) } } // Filename assigns a filename to parsed content. func Filename(filename string) BuildOption { return func(o *runtime.Config) { o.Filename = filename } } // ImportPath defines the import path to use for building CUE. The import path // influences the scope in which identifiers occurring in the input CUE are // defined. Passing the empty string is equal to not specifying this option. // // This option is typically not necessary when building using a build.Instance, // but takes precedence otherwise. func ImportPath(path string) BuildOption { return func(o *runtime.Config) { o.ImportPath = path } } // InferBuiltins allows unresolved references to bind to builtin packages with a // unique package name. // // This option is intended for evaluating expressions in a context where import // statements cannot be used. It is not recommended to use this for evaluating // CUE files. func InferBuiltins(elide bool) BuildOption { return func(o *runtime.Config) { o.Imports = func(x *ast.Ident) (pkgPath string) { return o.Runtime.BuiltinPackagePath(x.Name) } } } func (c *Context) parseOptions(options []BuildOption) (cfg runtime.Config) { cfg.Runtime = (*runtime.Runtime)(c) for _, f := range options { f(&cfg) } return cfg } // BuildInstance creates a [Value] from the given [*build.Instance]. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. func (c *Context) BuildInstance(i *build.Instance, options ...BuildOption) Value { cfg := c.parseOptions(options) v, err := c.runtime().Build(&cfg, i) if err != nil { return c.makeError(err) } return c.make(v) } func (c *Context) makeError(err errors.Error) Value { b := &adt.Bottom{Err: err} node := &adt.Vertex{BaseValue: b} node.ForceDone() node.AddConjunct(adt.MakeRootConjunct(nil, b)) return c.make(node) } // BuildInstances creates a [Value] for each of the given [*build.Instance]s and reports // the combined errors or nil if there were no errors. func (c *Context) BuildInstances(instances []*build.Instance) ([]Value, error) { var errs errors.Error var a []Value for _, b := range instances { v, err := c.runtime().Build(nil, b) if err != nil { errs = errors.Append(errs, err) a = append(a, c.makeError(err)) } else { a = append(a, c.make(v)) } } return a, errs } // BuildFile creates a [Value] from f. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. func (c *Context) BuildFile(f *ast.File, options ...BuildOption) Value { cfg := c.parseOptions(options) return c.compile(c.runtime().CompileFile(&cfg, f)) } func (c *Context) compile(v *adt.Vertex, p *build.Instance) Value { if p.Err != nil { return c.makeError(p.Err) } return c.make(v) } // BuildExpr creates a [Value] from x. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. func (c *Context) BuildExpr(x ast.Expr, options ...BuildOption) Value { r := c.runtime() cfg := c.parseOptions(options) ctx := c.ctx() // TODO: move to runtime?: it probably does not make sense to treat BuildExpr // and the expression resulting from CompileString differently. astutil.ResolveExpr(x, errFn) pkgPath := cmp.Or(cfg.ImportPath, anonymousPkg) conjunct, err := compile.Expr(&cfg.Config, r, pkgPath, x) if err != nil { return c.makeError(err) } v := adt.Resolve(ctx, conjunct) return c.make(v) } func errFn(pos token.Pos, msg string, args ...interface{}) {} // resolveExpr binds unresolved expressions to values in the expression or v. func resolveExpr(ctx *adt.OpContext, v Value, x ast.Expr) adt.Value { cfg := &compile.Config{Scope: valueScope(v)} astutil.ResolveExpr(x, errFn) c, err := compile.Expr(cfg, ctx, anonymousPkg, x) if err != nil { return &adt.Bottom{Err: err} } return adt.Resolve(ctx, c) } // anonymousPkg reports a package path that can never resolve to a valid package. const anonymousPkg = "_" // CompileString parses and builds a [Value] from the given source string. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. func (c *Context) CompileString(src string, options ...BuildOption) Value { cfg := c.parseOptions(options) return c.compile(c.runtime().Compile(&cfg, src)) } // CompileBytes parses and builds a [Value] from the given source bytes. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. func (c *Context) CompileBytes(b []byte, options ...BuildOption) Value { cfg := c.parseOptions(options) return c.compile(c.runtime().Compile(&cfg, b)) } // TODO: fs.FS or custom wrapper? // // CompileFile parses and build a Value from the given source bytes. // // // // The returned Value will represent an error, accessible through Err, if any // // error occurred. // func (c *Context) CompileFile(f fs.File, options ...BuildOption) Value { // b, err := io.ReadAll(f) // if err != nil { // return c.makeError(errors.Promote(err, "parsing file system file")) // } // return c.compile(c.runtime().Compile("", b)) // } func (c *Context) make(v *adt.Vertex) Value { opCtx := newContext(c.runtime()) // TODO: this is currently needed to ensure that node is properly recognized // as evaluated. Not dereferencing nodes, however, will have the benefit of // retaining more information. Remove the indirection when the code will be // able to properly handle this. x := newValueRoot(c.runtime(), opCtx, v) adt.AddStats(opCtx) return x } // An EncodeOption defines options for the various encoding-related methods of // [Context]. type EncodeOption func(*encodeOptions) type encodeOptions struct { nilIsTop bool } func (o *encodeOptions) process(option []EncodeOption) { for _, f := range option { f(o) } } // NilIsAny indicates whether a nil value is interpreted as null or _. // // The default is to interpret nil as _. func NilIsAny(isAny bool) EncodeOption { return func(o *encodeOptions) { o.nilIsTop = isAny } } // Encode converts a Go value to a CUE [Value]. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. // // Encode traverses the value v recursively. If an encountered value implements // the json.Marshaler interface and is not a nil pointer, Encode calls its // MarshalJSON method to produce JSON and convert that to CUE instead. If no // MarshalJSON method is present but the value implements encoding.TextMarshaler // instead, Encode calls its MarshalText method and encodes the result as a // string. // // Otherwise, Encode uses the following type-dependent default encodings: // // Boolean values encode as CUE booleans. // // Floating point, integer, and *big.Int and *big.Float values encode as CUE // numbers. // // String values encode as CUE strings coerced to valid UTF-8, replacing // sequences of invalid bytes with the Unicode replacement rune as per Unicode's // and W3C's recommendation. // // Array and slice values encode as CUE lists, except that []byte encodes as a // bytes value, and a nil slice encodes as the null. // // Struct values encode as CUE structs. Each exported struct field becomes a // member of the object, using the field name as the object key, unless the // field is omitted for one of the reasons given below. // // The encoding of each struct field can be customized by the format string // stored under the "json" key in the struct field's tag. The format string // gives the name of the field, possibly followed by a comma-separated list of // options. The name may be empty in order to specify options without overriding // the default field name. // // The "omitempty" option specifies that the field should be omitted from the // encoding if the field has an empty value, defined as false, 0, a nil pointer, // a nil interface value, and any empty array, slice, map, or string. // // See the documentation for Go's json.Marshal for more details on the field // tags and their meaning. // // Anonymous struct fields are usually encoded as if their inner exported // fields were fields in the outer struct, subject to the usual Go visibility // rules amended as described in the next paragraph. An anonymous struct field // with a name given in its JSON tag is treated as having that name, rather than // being anonymous. An anonymous struct field of interface type is treated the // same as having that type as its name, rather than being anonymous. // // The Go visibility rules for struct fields are amended for when deciding which // field to encode or decode. If there are multiple fields at the same level, // and that level is the least nested (and would therefore be the nesting level // selected by the usual Go rules), the following extra rules apply: // // 1) Of those fields, if any are JSON-tagged, only tagged fields are // considered, even if there are multiple untagged fields that would otherwise // conflict. // // 2) If there is exactly one field (tagged or not according to the first rule), // that is selected. // // 3) Otherwise there are multiple fields, and all are ignored; no error occurs. // // Map values encode as CUE structs. The map's key type must either be a string, // an integer type, or implement encoding.TextMarshaler. The map keys are sorted // and used as CUE struct field names by applying the following rules, subject // to the UTF-8 coercion described for string values above: // // - keys of any string type are used directly // - encoding.TextMarshalers are marshaled // - integer keys are converted to strings // // Pointer values encode as the value pointed to. A nil pointer encodes as the // null CUE value. // // Interface values encode as the value contained in the interface. A nil // interface value encodes as the null CUE value. The NilIsAny EncodingOption // can be used to interpret nil as any (_) instead. // // Channel, complex, and function values cannot be encoded in CUE. Attempting to // encode such a value results in the returned value being an error, accessible // through the Err method. func (c *Context) Encode(x interface{}, option ...EncodeOption) Value { switch v := x.(type) { case adt.Value: return newValueRoot(c.runtime(), c.ctx(), v) } var options encodeOptions options.process(option) ctx := c.ctx() // TODO: is true the right default? expr := convert.GoValueToValue(ctx, x, options.nilIsTop) var n *adt.Vertex if v, ok := expr.(*adt.Vertex); ok { n = v } else { n = &adt.Vertex{} n.AddConjunct(adt.MakeRootConjunct(nil, expr)) } n.Finalize(ctx) return c.make(n) } // Encode converts a Go type to a CUE [Value]. // // The returned value will represent an error, accessible through [Value.Err], // if any error occurred. func (c *Context) EncodeType(x interface{}, option ...EncodeOption) Value { switch v := x.(type) { case *adt.Vertex: return c.make(v) } ctx := c.ctx() expr, err := convert.GoTypeToExpr(ctx, x) if err != nil { return c.makeError(err) } var n *adt.Vertex if v, ok := expr.(*adt.Vertex); ok { n = v } else { n = &adt.Vertex{} n.AddConjunct(adt.MakeRootConjunct(nil, expr)) } n.Finalize(ctx) return c.make(n) } // NewList creates a Value that is a list of the given values. // // All Values must be created by c. func (c *Context) NewList(v ...Value) Value { a := make([]adt.Value, len(v)) for i, x := range v { if x.idx != (*runtime.Runtime)(c) { panic("values must be from same Context") } a[i] = x.v } return c.make(c.ctx().NewList(a...)) } // TODO: // func (c *Context) NewExpr(op Op, v ...Value) Value { // return Value{} // } // func (c *Context) NewValue(v ...ValueElem) Value { // return Value{} // } // func NewAttr(key string, values ...string) *Attribute { // return &Attribute{} // } // // Clear unloads all previously-loaded imports. // func (c *Context) Clear() { // } // // Values created up to the point of the Fork will be valid in both runtimes. // func (c *Context) Fork() *Context { // return nil // } // type ValueElem interface { // } // func NewField(sel Selector, value Value, attrs ...Attribute) ValueElem { // return nil // } // func NewDocComment(text string) ValueElem { // return nil // } // newContext returns a new evaluation context. func newContext(idx *runtime.Runtime) *adt.OpContext { if idx == nil { return nil } return eval.NewContext(idx, nil) } func debugStr(ctx *adt.OpContext, v adt.Node) string { return debug.NodeString(ctx, v, nil) } func str(c *adt.OpContext, v adt.Node) string { return debugStr(c, v) } // eval returns the evaluated value. This may not be the vertex. // // Deprecated: use [adt.OpContext.value]. func (v Value) eval(ctx *adt.OpContext) adt.Value { if v.v == nil { panic("undefined value") } x := manifest(ctx, v.v) return x.Value() } // TODO: change from Vertex to Vertex. func manifest(ctx *adt.OpContext, v *adt.Vertex) *adt.Vertex { v.Finalize(ctx) return v } cue-lang-cue-db9cc73/cue/context_test.go000066400000000000000000000103551474664451600203320ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/internal/astinternal" "cuelang.org/go/internal/cuetest" "cuelang.org/go/internal/cuetxtar" "cuelang.org/go/internal/tdtest" "github.com/go-quicktest/qt" "golang.org/x/tools/txtar" ) func TestNewList(t *testing.T) { ctx := cuecontext.New() intList := ctx.CompileString("[...int]") l123 := ctx.NewList( ctx.Encode(1), ctx.Encode(2), ctx.Encode(3), ) testCases := []struct { desc string v cue.Value out string }{{ v: ctx.NewList(), out: `[]`, }, { v: l123, out: `[1, 2, 3]`, }, { v: l123.Unify(intList), out: `[1, 2, 3]`, }, { v: l123.Unify(intList).Unify(l123), out: `[1, 2, 3]`, }, { v: intList.Unify(ctx.NewList(ctx.Encode("string"))), out: `_|_ // 0: conflicting values "string" and int (mismatched types string and int)`, }, { v: ctx.NewList().Unify(l123), out: `_|_ // incompatible list lengths (0 and 3)`, }, { v: ctx.NewList( intList, intList, ).Unify(ctx.NewList( ctx.NewList( ctx.Encode(1), ctx.Encode(3), ), ctx.NewList( ctx.Encode(5), ctx.Encode(7), ), )), out: `[[1, 3], [5, 7]]`, }} for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { got := fmt.Sprint(tc.v) if got != tc.out { t.Errorf(" got: %v\nwant: %v", got, tc.out) } }) } } func TestBuildInstancesSuccess(t *testing.T) { in := ` -- foo.cue -- package foo foo: [{a: "b", c: "d"}, {a: "e", g: "f"}] bar: [ for f in foo if (f & {c: "b"}) != _|_ {f} ] ` a := txtar.Parse([]byte(in)) instance := cuetxtar.Load(a, t.TempDir())[0] if instance.Err != nil { t.Fatal(instance.Err) } _, err := cuecontext.New().BuildInstances([]*build.Instance{instance}) if err != nil { t.Fatalf("BuildInstances() = %v", err) } } func TestBuildInstancesError(t *testing.T) { in := ` -- foo.cue -- package foo foo: [{a: "b", c: "d"}, {a: "e", g: "f"}] bar: [ for f in foo if f & {c: "b") != _|_ // NOTE: ')' instead of '}' {f} ] ` a := txtar.Parse([]byte(in)) instance := cuetxtar.Load(a, t.TempDir())[0] // Normally, this should be checked, however, this is explicitly // testing the path where this was NOT checked. // if instance.Err != nil { // t.Fatal(instance.Err) // } vs, err := cuecontext.New().BuildInstances([]*build.Instance{instance}) if err == nil { t.Fatalf("BuildInstances() = %#v, wanted error", vs) } } func TestEncodeType(t *testing.T) { type testCase struct { name string x interface{} wantErr string out string } testCases := []testCase{{ name: "Struct", x: struct { A int `json:"a"` B string `json:"b,omitempty"` C []bool }{}, out: `{a: int64, b?: string, C?: *null|[...bool]}`, }, { name: "CUEValue#1", x: struct { A cue.Value `json:"a"` }{}, out: `{a: _}`, }, { name: "CUEValue#2", x: cue.Value{}, out: `_`, }, { // TODO this looks like a shortcoming of EncodeType. name: "map", x: map[string]int{}, out: `*null|{}`, }, { name: "slice", x: []int{}, out: `*null|[...int64]`, }, { name: "chan", x: chan int(nil), wantErr: `unsupported Go type \(chan int\)`, }} tdtest.Run(t, testCases, func(t *cuetest.T, tc *testCase) { v := cuecontext.New().EncodeType(tc.x) if tc.wantErr != "" { qt.Assert(t, qt.ErrorMatches(v.Err(), tc.wantErr)) return } qt.Assert(t, qt.IsNil(v.Err())) got := fmt.Sprint(astinternal.DebugStr(v.Eval().Syntax())) t.Equal(got, tc.out) }) } func TestContextCheck(t *testing.T) { qt.Assert(t, qt.PanicMatches(func() { var c cue.Context c.CompileString("1") }, `.*use cuecontext\.New.*`)) } cue-lang-cue-db9cc73/cue/cue.go000066400000000000000000000033351474664451600163630ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package cue is the main API for CUE evaluation. // // [Value] is the main type that represents CUE evaluations. // Values are created with a [cuelang.org/go/cue/cuecontext.Context]. // Only values created from the same Context can be involved in the same operation. // Values created from the same Context are not safe for concurrent use, // which we intend to change in the future. // // [Context] defines the set of active packages, the translations of field // names to unique codes, as well as the set of builtins. // Use [cuelang.org/go/cue/cuecontext.New] to create a new context. // // While a context can be used to build values, note that loading a module and its // dependencies should be done with the [cuelang.org/go/cue/load] package. // // Note that the following types are DEPRECATED and their usage should be // avoided if possible: // // - [FieldInfo] // - [Instance] // - [Runtime] // - [Struct] // // Many types also have deprecated methods. Code that already uses deprecated // methods can keep using them for at least some time. We aim to provide a // go or cue fix solution to automatically rewrite code using the new API. package cue cue-lang-cue-db9cc73/cue/cuecontext/000077500000000000000000000000001474664451600174355ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/cuecontext/cuecontext.go000066400000000000000000000064061474664451600221530ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cuecontext import ( "fmt" "cuelang.org/go/cue" "cuelang.org/go/internal" "cuelang.org/go/internal/core/runtime" "cuelang.org/go/internal/cuedebug" "cuelang.org/go/internal/envflag" _ "cuelang.org/go/pkg" ) // Option controls a build context. type Option struct { apply func(r *runtime.Runtime) } // New creates a new [*cue.Context]. // // The environment variables CUE_EXPERIMENT and CUE_DEBUG are followed to configure // the evaluator, just like the cue tool documents via [cue help environment]. // You can override these settings via options like [EvaluatorVersion] and [CUE_DEBUG]. // // [cue help environment]: https://cuelang.org/docs/reference/command/cue-help-environment/ func New(options ...Option) *cue.Context { r := runtime.New() for _, o := range options { o.apply(r) } return (*cue.Context)(r) } // An ExternInterpreter creates a compiler that can produce implementations of // functions written in a language other than CUE. It is currently for internal // use only. type ExternInterpreter = runtime.Interpreter // Interpreter associates an interpreter for external code with this context. func Interpreter(i ExternInterpreter) Option { return Option{func(r *runtime.Runtime) { r.SetInterpreter(i) }} } type EvalVersion = internal.EvaluatorVersion const ( // EvalDefault is the latest stable version of the evaluator. EvalDefault EvalVersion = internal.DefaultVersion // EvalExperiment refers to the latest unstable version of the evaluator. // Note that this version may change without notice. EvalExperiment EvalVersion = internal.DevVersion // EvalV2 is the currently latest stable version of the evaluator. // It was introduced in CUE version 0.3 and is being maintained until 2024. EvalV2 EvalVersion = internal.EvalV2 // EvalV3 is the currently experimental version of the evaluator. // It was introduced in 2024 and brought a new disjunction algorithm, // a new closedness algorithm, a new core scheduler, and adds performance // enhancements like structure sharing. EvalV3 EvalVersion = internal.EvalV3 ) // EvaluatorVersion indicates which version of the evaluator to use. Currently // only experimental versions can be selected as an alternative. func EvaluatorVersion(v EvalVersion) Option { return Option{func(r *runtime.Runtime) { r.SetVersion(v) }} } // CUE_DEBUG takes a string with the same contents as CUE_DEBUG and configures // the context with the relevant debug options. It panics for unknown or // malformed options. func CUE_DEBUG(s string) Option { var c cuedebug.Config if err := envflag.Parse(&c, s); err != nil { panic(fmt.Errorf("cuecontext.CUE_DEBUG: %v", err)) } return Option{func(r *runtime.Runtime) { r.SetDebugOptions(&c) }} } cue-lang-cue-db9cc73/cue/cuecontext/cuecontext_test.go000066400000000000000000000046071474664451600232130ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cuecontext import ( "fmt" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/internal" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/runtime" "cuelang.org/go/internal/cueexperiment" ) func TestAPI(t *testing.T) { testCases := []struct { name string fun func() cue.Value want string }{{ name: "issue1204", fun: func() cue.Value { ctx := New() expr := ast.NewCall(ast.NewIdent("close"), ast.NewStruct()) return ctx.BuildExpr(expr) }, want: `close({})`, }, { name: "issue1131", fun: func() cue.Value { m := make(map[string]interface{}) ctx := New() cv := ctx.Encode(m) return cv }, want: "", // empty file. }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got := fmt.Sprintf("%#v", tc.fun()) if got != tc.want { t.Errorf("got:\n%v;\nwant:\n%v", got, tc.want) } }) } } // TestConcurrency tests whether concurrent use of an index is allowed. // This test only functions well with the --race flag. func TestConcurrency(t *testing.T) { c := New() go func() { c.CompileString(` package foo a: 1 `) }() go func() { c.CompileString(` package bar a: 2 `) }() } func TestEvalVersion(t *testing.T) { cueexperiment.Init() saved := cueexperiment.Flags.EvalV3 defer func() { cueexperiment.Flags.EvalV3 = saved }() test := func(c *cue.Context, want internal.EvaluatorVersion) { opCtx := adt.NewContext((*runtime.Runtime)(c), nil) got := opCtx.Version if got != want { t.Errorf("got %v; want %v", got, want) } } cueexperiment.Flags.EvalV3 = true test(New(), internal.DevVersion) test(New(EvaluatorVersion(EvalV2)), internal.DefaultVersion) test(New(EvaluatorVersion(EvalV3)), internal.DevVersion) cueexperiment.Flags.EvalV3 = false test(New(), internal.DefaultVersion) } cue-lang-cue-db9cc73/cue/decode.go000066400000000000000000000550451474664451600170370ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "bytes" "cmp" "encoding" "encoding/json" "math" "reflect" "slices" "strconv" "strings" "sync" "unicode" "unicode/utf8" "cuelang.org/go/cue/errors" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/cueexperiment" ) // Decode initializes the value pointed to by x with Value v. // An error is returned if x is nil or not a pointer. // // If x is a struct, Decode will validate the constraints specified in the field tags. // // If x contains a [Value], that part of x will be set to the value // at the corresponding part of v. This allows decoding values // that aren't entirely concrete into a Go type. func (v Value) Decode(x interface{}) error { var d decoder w := reflect.ValueOf(x) if w.Kind() != reflect.Pointer || w.IsNil() { d.addErr(errors.Newf(v.Pos(), "cannot decode into unsettable value")) return d.errs } d.decode(w.Elem(), v, false) return d.errs } type decoder struct { errs errors.Error } func (d *decoder) addErr(err error) { if err != nil { d.errs = errors.Append(d.errs, errors.Promote(err, "")) } } func incompleteError(v Value) errors.Error { return &valueError{ v: v, err: &adt.Bottom{ Code: adt.IncompleteError, Err: errors.Newf(v.Pos(), "cannot convert non-concrete value %v", v)}, } } func (d *decoder) clear(x reflect.Value) { if x.CanSet() { x.SetZero() } } var valueType = reflect.TypeFor[Value]() func (d *decoder) decode(x reflect.Value, v Value, isPtr bool) { if !x.IsValid() { d.addErr(errors.Newf(v.Pos(), "cannot decode into invalid value")) return } v, _ = v.Default() if v.v == nil { d.clear(x) return } if err := v.Err(); err != nil { d.addErr(err) return } if x.Type() == valueType { x.Set(reflect.ValueOf(v)) return } switch x.Kind() { case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface: // nullable types if v.IsNull() || !v.IsConcrete() { d.clear(x) return } default: // TODO: allow incomplete values. if !v.IsConcrete() { d.addErr(incompleteError(v)) return } } ij, it, x := indirect(x, v.IsNull()) if ij != nil { b, err := v.MarshalJSON() d.addErr(err) d.addErr(ij.UnmarshalJSON(b)) return } if it != nil { b, err := v.Bytes() if err != nil { err = errors.Wrapf(err, v.Pos(), "Decode") d.addErr(err) return } d.addErr(it.UnmarshalText(b)) return } kind := x.Kind() if kind == reflect.Interface { value := d.interfaceValue(v) x.Set(reflect.ValueOf(value)) return } switch kind { case reflect.Ptr: d.decode(x.Elem(), v, true) case reflect.Bool: b, err := v.Bool() d.addErr(err) x.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: i, err := v.Int64() d.addErr(err) if x.OverflowInt(i) { d.addErr(errors.Newf(v.Pos(), "integer %d overflows %s", i, kind)) break } x.SetInt(i) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: i, err := v.Uint64() d.addErr(err) if x.OverflowUint(i) { d.addErr(errors.Newf(v.Pos(), "integer %d overflows %s", i, kind)) break } x.SetUint(i) case reflect.Float32, reflect.Float64: f, err := v.Float64() d.addErr(err) if x.OverflowFloat(f) { d.addErr(errors.Newf(v.Pos(), "float %g overflows %s", f, kind)) break } x.SetFloat(f) case reflect.String: s, err := v.String() d.addErr(err) x.SetString(s) case reflect.Array: d.clear(x) t := x.Type() n := x.Len() if t.Elem().Kind() == reflect.Uint8 && v.Kind() == BytesKind { b, err := v.Bytes() d.addErr(err) for i, c := range b { if i >= n { break } x.Index(i).SetUint(uint64(c)) } break } var a []Value list, err := v.List() d.addErr(err) for list.Next() { a = append(a, list.Value()) } for i, v := range a { if i >= n { break } d.decode(x.Index(i), v, false) } case reflect.Slice: t := x.Type() if t.Elem().Kind() == reflect.Uint8 && v.Kind() == BytesKind { b, err := v.Bytes() d.addErr(err) x.SetBytes(b) break } var a []Value list, err := v.List() d.addErr(err) for list.Next() { a = append(a, list.Value()) } switch cap := x.Cap(); { case cap == 0, // force a non-nil list cap < len(a): x.Set(reflect.MakeSlice(t, len(a), len(a))) default: x.SetLen(len(a)) } for i, v := range a { d.decode(x.Index(i), v, false) } case reflect.Struct: d.convertStruct(x, v) case reflect.Map: d.convertMap(x, v) default: d.clear(x) } } func (d *decoder) interfaceValue(v Value) (x interface{}) { var err error v, _ = v.Default() switch v.Kind() { case NullKind: return nil case BoolKind: x, err = v.Bool() case IntKind: if i, err := v.Int64(); err == nil { cueexperiment.Init() if cueexperiment.Flags.DecodeInt64 { return i } // When the decodeint64 experiment is not enabled, we want to return the value // as `int`, but that's not possible for large values on 32-bit architectures. // To avoid overflows causing entirely wrong values to be returned to the user, // let the logic continue below so that we return a *big.Int instead. if i <= math.MaxInt && i >= math.MinInt { return int(i) } } x, err = v.Int(nil) case FloatKind: x, err = v.Float64() // or big int or case StringKind: x, err = v.String() case BytesKind: x, err = v.Bytes() case ListKind: var a []interface{} list, err := v.List() d.addErr(err) for list.Next() { a = append(a, d.interfaceValue(list.Value())) } if a == nil { a = []interface{}{} } x = a case StructKind: m := map[string]interface{}{} iter, err := v.Fields() d.addErr(err) for iter.Next() { m[iter.Selector().Unquoted()] = d.interfaceValue(iter.Value()) } x = m default: err = incompleteError(v) } d.addErr(err) return x } var textUnmarshalerType = reflect.TypeFor[encoding.TextUnmarshaler]() // convertMap keeps an existing map and overwrites any entry found in v, // keeping other preexisting entries. func (d *decoder) convertMap(x reflect.Value, v Value) { // Delete existing elements t := x.Type() // Map key must either have string kind, have an integer kind, // or be an encoding.TextUnmarshaler. switch t.Key().Kind() { case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: default: if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) { d.addErr(errors.Newf(v.Pos(), "unsupported key type %v", t.Key())) return } } if x.IsNil() { x.Set(reflect.MakeMap(t)) } var mapElem reflect.Value iter, err := v.Fields() d.addErr(err) for iter.Next() { key := iter.Selector().Unquoted() var kv reflect.Value kt := t.Key() if reflect.PointerTo(kt).Implements(textUnmarshalerType) { kv = reflect.New(kt) err := kv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(key)) d.addErr(err) kv = kv.Elem() } else { switch kt.Kind() { case reflect.String: kv = reflect.ValueOf(key).Convert(kt) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(key, 10, 64) d.addErr(err) if reflect.Zero(kt).OverflowInt(n) { d.addErr(errors.Newf(v.Pos(), "key integer %d overflows %s", n, kt)) break } kv = reflect.ValueOf(n).Convert(kt) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(key, 10, 64) d.addErr(err) if reflect.Zero(kt).OverflowUint(n) { d.addErr(errors.Newf(v.Pos(), "key integer %d overflows %s", n, kt)) break } kv = reflect.ValueOf(n).Convert(kt) default: panic("json: Unexpected key type") // should never occur } } if !mapElem.IsValid() { mapElem = reflect.New(t.Elem()).Elem() } else { mapElem.SetZero() } d.decode(mapElem, iter.Value(), false) if kv.IsValid() { x.SetMapIndex(kv, mapElem) } } } func (d *decoder) convertStruct(x reflect.Value, v Value) { t := x.Type() fields := cachedTypeFields(t) iter, err := v.Fields() d.addErr(err) for iter.Next() { var f *goField key := iter.Selector().Unquoted() if i, ok := fields.nameIndex[key]; ok { // Found an exact name match. f = &fields.list[i] } else { // Fall back to the expensive case-insensitive // linear search. key := []byte(key) for i := range fields.list { ff := &fields.list[i] if ff.equalFold(ff.nameBytes, key) { f = ff break } } } if f == nil { continue } // Figure out field corresponding to key. subv := x for _, i := range f.index { if subv.Kind() == reflect.Ptr { if subv.IsNil() { // If a struct embeds a pointer to an unexported type, // it is not possible to set a newly allocated value // since the field is unexported. // // See https://golang.org/issue/21357 if !subv.CanSet() { d.addErr(errors.Newf(v.Pos(), "cannot set embedded pointer to unexported struct: %v", subv.Type().Elem())) subv = reflect.Value{} break } subv.Set(reflect.New(subv.Type().Elem())) } subv = subv.Elem() } subv = subv.Field(i) } // TODO: make this an option // else if d.disallowUnknownFields { // d.saveError(fmt.Errorf("json: unknown field %q", key)) // } d.decode(subv, iter.Value(), false) } } type structFields struct { list []goField nameIndex map[string]int } func isValidTag(s string) bool { if s == "" { return false } for _, c := range s { switch { case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c): // Backslash and quote chars are reserved, but // otherwise any punctuation chars are allowed // in a tag name. case !unicode.IsLetter(c) && !unicode.IsDigit(c): return false } } return true } // A field represents a single Go field found in a struct. type goField struct { name string nameBytes []byte // []byte(name) equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent tag bool index []int typ reflect.Type omitEmpty bool } func compareFieldByIndex(a, b goField) int { for i, x := range a.index { if i >= len(b.index) { break } if c := cmp.Compare(x, b.index[i]); c != 0 { return c } } return cmp.Compare(len(a.index), len(b.index)) } // typeFields returns a list of fields that JSON should recognize for the given type. // The algorithm is breadth-first search over the set of structs to include - the top struct // and then any reachable anonymous structs. func typeFields(t reflect.Type) structFields { // Anonymous fields to explore at the current level and the next. current := []goField{} next := []goField{{typ: t}} // Count of queued names for current level and the next. var count, nextCount map[reflect.Type]int // Types already visited at an earlier level. visited := map[reflect.Type]bool{} // Fields found. var fields []goField for len(next) > 0 { current, next = next, current[:0] count, nextCount = nextCount, map[reflect.Type]int{} for _, f := range current { if visited[f.typ] { continue } visited[f.typ] = true // Scan f.typ for fields to include. for i := 0; i < f.typ.NumField(); i++ { sf := f.typ.Field(i) isUnexported := sf.PkgPath != "" if sf.Anonymous { t := sf.Type if t.Kind() == reflect.Ptr { t = t.Elem() } if isUnexported && t.Kind() != reflect.Struct { // Ignore embedded fields of unexported non-struct types. continue } // Do not ignore embedded fields of unexported struct types // since they may have exported fields. } else if isUnexported { // Ignore unexported non-embedded fields. continue } tag := sf.Tag.Get("json") if tag == "-" { continue } name, opts := parseTag(tag) if !isValidTag(name) { name = "" } index := make([]int, len(f.index)+1) copy(index, f.index) index[len(f.index)] = i ft := sf.Type if ft.Name() == "" && ft.Kind() == reflect.Ptr { // Follow pointer. ft = ft.Elem() } // Record found field and index sequence. if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { tagged := name != "" if name == "" { name = sf.Name } field := goField{ name: name, tag: tagged, index: index, typ: ft, omitEmpty: opts.Contains("omitempty"), } field.nameBytes = []byte(field.name) field.equalFold = foldFunc(field.nameBytes) fields = append(fields, field) if count[f.typ] > 1 { // If there were multiple instances, add a second, // so that the annihilation code will see a duplicate. // It only cares about the distinction between 1 or 2, // so don't bother generating any more copies. fields = append(fields, fields[len(fields)-1]) } continue } // Record new anonymous struct to explore in next round. nextCount[ft]++ if nextCount[ft] == 1 { next = append(next, goField{name: ft.Name(), index: index, typ: ft}) } } } } slices.SortFunc(fields, func(a, b goField) int { // sort field by name, breaking ties with depth, then // breaking ties with "name came from json tag", then // breaking ties with index sequence. if c := cmp.Compare(a.name, b.name); c != 0 { return c } if c := cmp.Compare(len(a.index), len(b.index)); c != 0 { return c } if a.tag != b.tag { if a.tag { return 1 } else { return -1 } } return compareFieldByIndex(a, b) }) // Delete all fields that are hidden by the Go rules for embedded fields, // except that fields with JSON tags are promoted. // The fields are sorted in primary order of name, secondary order // of field index length. Loop over names; for each name, delete // hidden fields by choosing the one dominant field that survives. out := fields[:0] for advance, i := 0, 0; i < len(fields); i += advance { // One iteration per name. // Find the sequence of fields with the name of this first field. fi := fields[i] name := fi.name for advance = 1; i+advance < len(fields); advance++ { fj := fields[i+advance] if fj.name != name { break } } if advance == 1 { // Only one field with this name out = append(out, fi) continue } dominant, ok := dominantField(fields[i : i+advance]) if ok { out = append(out, dominant) } } fields = out slices.SortFunc(fields, compareFieldByIndex) nameIndex := make(map[string]int, len(fields)) for i, field := range fields { nameIndex[field.name] = i } return structFields{fields, nameIndex} } // dominantField looks through the fields, all of which are known to // have the same name, to find the single field that dominates the // others using Go's embedding rules, modified by the presence of // JSON tags. If there are multiple top-level fields, the boolean // will be false: This condition is an error in Go and we skip all // the fields. func dominantField(fields []goField) (goField, bool) { // The fields are sorted in increasing index-length order, then by presence of tag. // That means that the first field is the dominant one. We need only check // for error cases: two fields at top level, either both tagged or neither tagged. if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag { return goField{}, false } return fields[0], true } var fieldCache sync.Map // map[reflect.Type]structFields // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. func cachedTypeFields(t reflect.Type) structFields { if f, ok := fieldCache.Load(t); ok { return f.(structFields) } f, _ := fieldCache.LoadOrStore(t, typeFields(t)) return f.(structFields) } // tagOptions is the string following a comma in a struct field's "json" // tag, or the empty string. It does not include the leading comma. type tagOptions string // parseTag splits a struct field's json tag into its name and // comma-separated options. func parseTag(tag string) (string, tagOptions) { if idx := strings.Index(tag, ","); idx != -1 { return tag[:idx], tagOptions(tag[idx+1:]) } return tag, tagOptions("") } // Contains reports whether a comma-separated list of options // contains a particular substr flag. substr must be surrounded by a // string boundary or commas. func (o tagOptions) Contains(optionName string) bool { if len(o) == 0 { return false } s := string(o) for s != "" { var next string i := strings.Index(s, ",") if i >= 0 { s, next = s[:i], s[i+1:] } if s == optionName { return true } s = next } return false } // foldFunc returns one of four different case folding equivalence // functions, from most general (and slow) to fastest: // // 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8 // 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S') // 3) asciiEqualFold, no special, but includes non-letters (including _) // 4) simpleLetterEqualFold, no specials, no non-letters. // // The letters S and K are special because they map to 3 runes, not just 2: // - S maps to s and to U+017F 'ſ' Latin small letter long s // - k maps to K and to U+212A 'K' Kelvin sign // // See https://play.golang.org/p/tTxjOc0OGo // // The returned function is specialized for matching against s and // should only be given s. It's not curried for performance reasons. func foldFunc(s []byte) func(s, t []byte) bool { nonLetter := false special := false // special letter for _, b := range s { if b >= utf8.RuneSelf { return bytes.EqualFold } upper := b & caseMask if upper < 'A' || upper > 'Z' { nonLetter = true } else if upper == 'K' || upper == 'S' { // See above for why these letters are special. special = true } } if special { return equalFoldRight } if nonLetter { return asciiEqualFold } return simpleLetterEqualFold } const ( caseMask = ^byte(0x20) // Mask to ignore case in ASCII. kelvin = '\u212a' smallLongEss = '\u017f' ) // equalFoldRight is a specialization of bytes.EqualFold when s is // known to be all ASCII (including punctuation), but contains an 's', // 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. // See comments on foldFunc. func equalFoldRight(s, t []byte) bool { for _, sb := range s { if len(t) == 0 { return false } tb := t[0] if tb < utf8.RuneSelf { if sb != tb { sbUpper := sb & caseMask if 'A' <= sbUpper && sbUpper <= 'Z' { if sbUpper != tb&caseMask { return false } } else { return false } } t = t[1:] continue } // sb is ASCII and t is not. t must be either kelvin // sign or long s; sb must be s, S, k, or K. tr, size := utf8.DecodeRune(t) switch sb { case 's', 'S': if tr != smallLongEss { return false } case 'k', 'K': if tr != kelvin { return false } default: return false } t = t[size:] } return len(t) == 0 } // asciiEqualFold is a specialization of bytes.EqualFold for use when // s is all ASCII (but may contain non-letters) and contains no // special-folding letters. // See comments on foldFunc. func asciiEqualFold(s, t []byte) bool { if len(s) != len(t) { return false } for i, sb := range s { tb := t[i] if sb == tb { continue } if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { if sb&caseMask != tb&caseMask { return false } } else { return false } } return true } // simpleLetterEqualFold is a specialization of bytes.EqualFold for // use when s is all ASCII letters (no underscores, etc) and also // doesn't contain 'k', 'K', 's', or 'S'. // See comments on foldFunc. func simpleLetterEqualFold(s, t []byte) bool { if len(s) != len(t) { return false } for i, b := range s { if b&caseMask != t[i]&caseMask { return false } } return true } // indirect walks down v allocating pointers as needed, // until it gets to a non-pointer. // If it encounters an Unmarshaler, indirect stops and returns that. // If decodingNull is true, indirect stops at the first settable pointer so it // can be set to nil. func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { // Issue #24153 indicates that it is generally not a guaranteed property // that you may round-trip a reflect.Value by calling Value.Addr().Elem() // and expect the value to still be settable for values derived from // unexported embedded struct fields. // // The logic below effectively does this when it first addresses the value // (to satisfy possible pointer methods) and continues to dereference // subsequent pointers as necessary. // // After the first round-trip, we set v back to the original value to // preserve the original RW flags contained in reflect.Value. v0 := v haveAddr := false // If v is a named type and is addressable, // start with its address, so that if the type has pointer methods, // we find them. if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { haveAddr = true v = v.Addr() } for { // Load value from interface, but only if the result will be // usefully addressable. if v.Kind() == reflect.Interface && !v.IsNil() { e := v.Elem() if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { haveAddr = false v = e continue } } if v.Kind() != reflect.Ptr { break } if decodingNull && v.CanSet() { break } // Prevent infinite loop if v is an interface pointing to its own address: // var v interface{} // v = &v if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v { v = v.Elem() break } if v.IsNil() { v.Set(reflect.New(v.Type().Elem())) } if v.Type().NumMethod() > 0 && v.CanInterface() { if u, ok := v.Interface().(json.Unmarshaler); ok { return u, nil, reflect.Value{} } if !decodingNull { if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { return nil, u, reflect.Value{} } } } if haveAddr { v = v0 // restore original value after round-trip Value.Addr().Elem() haveAddr = false } else { v = v.Elem() } } return nil, nil, v } cue-lang-cue-db9cc73/cue/decode_test.go000066400000000000000000000176161474664451600201000ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "math/big" "reflect" "testing" "time" "cuelang.org/go/cue" "cuelang.org/go/internal/cuetdtest" "github.com/go-quicktest/qt" "github.com/google/go-cmp/cmp" ) func TestDecode(t *testing.T) { type Nested struct { P *int `json:"P"` } type fields struct { A int `json:"A"` B int `json:"B"` C int `json:"C"` M map[string]interface{} *Nested } one := 1 intList := func(ints ...int) *[]int { ints = append([]int{}, ints...) return &ints } testCases := []struct { value string dst interface{} want interface{} err string }{{ // clear pointer value: `null`, dst: &[]int{1}, want: []int(nil), }, { value: `1`, err: "cannot decode into unsettable value", }, { dst: new(interface{}), value: `_|_`, err: "explicit error (_|_ literal) in source", }, { // clear pointer value: `null`, dst: &[]int{1}, want: []int(nil), }, { // clear pointer value: `[null]`, dst: &[]*int{&one}, want: []*int{nil}, }, { value: `true`, dst: new(bool), want: true, }, { value: `false`, dst: new(bool), want: false, }, { value: `bool`, dst: new(bool), err: "cannot convert non-concrete value bool", }, { value: `_`, dst: new([]int), want: []int(nil), }, { value: `"str"`, dst: new(string), want: "str", }, { value: `"str"`, dst: new(int), err: "cannot use value \"str\" (type string) as int", }, { value: `'bytes'`, dst: new([]byte), want: []byte("bytes"), }, { value: `'bytes'`, dst: &[3]byte{}, want: [3]byte{0x62, 0x79, 0x74}, }, { value: `1`, dst: new(float32), want: float32(1), }, { value: `500`, dst: new(uint8), err: "integer 500 overflows uint8", }, { value: `501`, dst: new(int8), err: "integer 501 overflows int8", }, { value: `{}`, dst: &fields{}, want: fields{}, }, { value: `{A:1,b:2,c:3}`, dst: &fields{}, want: fields{A: 1, B: 2, C: 3}, }, { // allocate map value: `{a:1,m:{a: 3}}`, dst: &fields{}, want: fields{A: 1, M: map[string]interface{}{"a": int64(3)}}, }, { // indirect int value: `{p: 1}`, dst: &fields{}, want: fields{Nested: &Nested{P: &one}}, }, { value: `{for k, v in y if v > 1 {"\(k)": v} } y: {a:1,b:2,c:3}`, dst: &fields{}, want: fields{B: 2, C: 3}, }, { value: `{a:1,b:2,c:int}`, dst: new(fields), err: "c: cannot convert non-concrete value int", }, { value: `[]`, dst: intList(), want: *intList(), }, { value: `[1,2,3]`, dst: intList(), want: *intList(1, 2, 3), }, { // shorten list value: `[1,2,3]`, dst: intList(1, 2, 3, 4), want: *intList(1, 2, 3), }, { // shorter array value: `[1,2,3]`, dst: &[2]int{}, want: [2]int{1, 2}, }, { // longer array value: `[1,2,3]`, dst: &[4]int{}, want: [4]int{1, 2, 3, 0}, }, { value: `[for x in #y if x > 1 { x }] #y: [1,2,3]`, dst: intList(), want: *intList(2, 3), }, { value: `[int]`, dst: intList(), err: "0: cannot convert non-concrete value int", }, { value: `{a: 1, b: 2, c: 3}`, dst: &map[string]int{}, want: map[string]int{"a": 1, "b": 2, "c": 3}, }, { value: `{"1": 1, "-2": 2, "3": 3}`, dst: &map[int]int{}, want: map[int]int{1: 1, -2: 2, 3: 3}, }, { value: `{"1": 1, "2": 2, "3": 3}`, dst: &map[uint]int{}, want: map[uint]int{1: 1, 2: 2, 3: 3}, }, { value: `{a: 1, b: 2, c: true, d: e: 2}`, dst: &map[string]interface{}{}, want: map[string]interface{}{ "a": int64(1), "b": int64(2), "c": true, "d": map[string]interface{}{"e": int64(2)}}, }, { value: `{a: b: *2 | int}`, dst: &map[string]interface{}{}, want: map[string]interface{}{"a": map[string]interface{}{"b": int64(2)}}, }, { value: `{a: 1, b: 2, c: true}`, dst: &map[string]int{}, err: "c: cannot use value true (type bool) as int", }, { value: `{"300": 3}`, dst: &map[int8]int{}, err: "key integer 300 overflows int8", }, { value: `{"300": 3}`, dst: &map[uint8]int{}, err: "key integer 300 overflows uint8", }, { // Issue #1401 value: `a: b: _ | *[0, ...]`, dst: &map[string]interface{}{}, want: map[string]interface{}{ "a": map[string]interface{}{ "b": []interface{}{int64(0)}, }, }, }, { // Issue #1466 value: `{"x": "1s"} `, dst: &S{}, want: S{X: Duration{D: 1000000000}}, }, { // Issue #1466 value: `{"x": '1s'} `, dst: &S{}, want: S{X: Duration{D: 1000000000}}, }, { // Issue #1466 value: `{"x": 1} `, dst: &S{}, err: "Decode: x: cannot use value 1 (type int) as (string|bytes)", }, { value: `[]`, dst: new(interface{}), want: []interface{}{}, }, { // large integer which doesn't fit into an int32 or int on 32-bit platforms value: `8000000000`, dst: new(interface{}), want: int64(8000000000), }, { // same as the above, but negative value: `-8000000000`, dst: new(interface{}), want: int64(-8000000000), }, { // even larger integer which doesn't fit into an int64 value: `9500000000000000000`, dst: new(interface{}), want: bigInt("9500000000000000000"), }, { // same as the above, but negative value: `-9500000000000000000`, dst: new(interface{}), want: bigInt("-9500000000000000000"), }, { // large float which doesn't fit into a float32 value: `1.797693134e+308`, dst: new(interface{}), want: float64(1.797693134e+308), }, { // even larger float which doesn't fit into a float64 // TODO(mvdan): this should work via *big.Float, just like we do with *big.Int above. value: `1.99769313499e+508`, dst: new(interface{}), err: "value was rounded up", }, { // same as the above, but negative // TODO(mvdan): this should work via *big.Float, just like we do with *big.Int above. value: `-1.99769313499e+508`, dst: new(interface{}), err: "value was rounded down", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { err := getValue(m, tc.value).Decode(tc.dst) checkFatal(t, err, tc.err, "init") got := reflect.ValueOf(tc.dst).Elem().Interface() if diff := cmp.Diff(got, tc.want, cmp.Comparer(func(a, b *big.Int) bool { return a.Cmp(b) == 0 })); diff != "" { t.Error(diff) t.Errorf("\n%#v\n%#v", got, tc.want) } }) } } func bigInt(s string) *big.Int { n, _ := big.NewInt(0).SetString(s, 10) return n } func TestDecodeIntoCUEValue(t *testing.T) { cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { // We should be able to decode into a CUE value so we can // decode partially incomplete values into Go. // This test doesn't fit within the table used by TestDecode // because cue values aren't easily comparable with cmp.Diff. var st struct { X cue.Value `json:"x"` } err := getValue(m, `x: string`).Decode(&st) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.Equals(fmt.Sprint(st.X), "string")) // Check we can decode into a top level value. var v cue.Value err = getValue(m, `int`).Decode(&v) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.Equals(fmt.Sprint(v), "int")) }) } type Duration struct { D time.Duration } type S struct { X Duration `json:"x"` } func (d *Duration) UnmarshalText(data []byte) error { v, err := time.ParseDuration(string(data)) if err != nil { return err } d.D = v return nil } func (d *Duration) MarshalText() ([]byte, error) { return []byte(d.D.String()), nil } cue-lang-cue-db9cc73/cue/embed_test.go000066400000000000000000000007001474664451600177130ustar00rootroot00000000000000package cue_test import ( "testing" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/interpreter/embed" "github.com/go-quicktest/qt" ) func TestEmbedFailsWhenNotInModule(t *testing.T) { ctx := cuecontext.New(cuecontext.Interpreter(embed.New())) v := ctx.CompileString(` @extern(embed) package foo x: _ @embed(file="testdata/readme.md",type=text) `) qt.Assert(t, qt.ErrorMatches(v.Err(), `cannot embed files when not in a module`)) } cue-lang-cue-db9cc73/cue/errors.go000066400000000000000000000055061474664451600171250ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/core/adt" ) func (v Value) toErr(b *adt.Bottom) (err errors.Error) { errs := errors.Errors(b.Err) if len(errs) > 1 { for _, e := range errs { bb := *b bb.Err = e err = errors.Append(err, &valueError{v: v, err: &bb}) } return err } return &valueError{v: v, err: b} } var _ errors.Error = &valueError{} // A valueError is returned as a result of evaluating a value. type valueError struct { v Value err *adt.Bottom } func (e *valueError) Unwrap() error { if e.err.Err == nil { return nil } return errors.Unwrap(e.err.Err) } func (e *valueError) Bottom() *adt.Bottom { return e.err } func (e *valueError) Error() string { return errors.String(e) } func (e *valueError) Position() token.Pos { if e.err.Err != nil { return e.err.Err.Position() } src := e.err.Source() if src == nil { return token.NoPos } return src.Pos() } func (e *valueError) InputPositions() []token.Pos { if e.err.Err == nil { return nil } return e.err.Err.InputPositions() } func (e *valueError) Msg() (string, []interface{}) { if e.err.Err == nil { return "", nil } return e.err.Err.Msg() } func (e *valueError) Path() (a []string) { if e.err.Err != nil { a = e.err.Err.Path() if a != nil { return a } } return pathToStrings(e.v.Path()) } var errNotExists = &adt.Bottom{ Code: adt.IncompleteError, NotExists: true, Err: errors.Newf(token.NoPos, "undefined value"), } func mkErr(src adt.Node, args ...interface{}) *adt.Bottom { var e *adt.Bottom var code adt.ErrorCode = -1 outer: for i, a := range args { switch x := a.(type) { case adt.ErrorCode: code = x case *adt.Bottom: e = adt.CombineErrors(nil, e, x) case []*adt.Bottom: for _, b := range x { e = adt.CombineErrors(nil, e, b) } case errors.Error: e = adt.CombineErrors(nil, e, &adt.Bottom{Err: x}) case adt.Expr: case string: args := args[i+1:] // Do not expand message so that errors can be localized. pos := pos(src) if code < 0 { code = 0 } e = adt.CombineErrors(nil, e, &adt.Bottom{ Code: code, Err: errors.Newf(pos, x, args...), }) break outer } } if code >= 0 { e.Code = code } return e } cue-lang-cue-db9cc73/cue/errors/000077500000000000000000000000001474664451600165705ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/errors/errors.go000066400000000000000000000354011474664451600204360ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package errors defines shared types for handling CUE errors. // // The pivotal error type in CUE packages is the interface type Error. // The information available in such errors can be most easily retrieved using // the Path, Positions, and Print functions. package errors import ( "cmp" "errors" "fmt" "io" "path/filepath" "slices" "strings" "cuelang.org/go/cue/token" ) // New is a convenience wrapper for [errors.New] in the core library. // It does not return a CUE error. func New(msg string) error { return errors.New(msg) } // Unwrap returns the result of calling the Unwrap method on err, if err // implements Unwrap. Otherwise, Unwrap returns nil. func Unwrap(err error) error { return errors.Unwrap(err) } // Is reports whether any error in err's chain matches target. // // An error is considered to match a target if it is equal to that target or if // it implements a method Is(error) bool such that Is(target) returns true. func Is(err, target error) bool { return errors.Is(err, target) } // As finds the first error in err's chain that matches the type to which target // points, and if so, sets the target to its value and returns true. An error // matches a type if it is assignable to the target type, or if it has a method // As(interface{}) bool such that As(target) returns true. As will panic if // target is not a non-nil pointer to a type which implements error or is of // interface type. // // The As method should set the target to its value and return true if err // matches the type to which target points. func As(err error, target interface{}) bool { return errors.As(err, target) } // A Message implements the error interface as well as Message to allow // internationalized messages. A Message is typically used as an embedding // in a CUE message. type Message struct { format string args []interface{} } // NewMessagef creates an error message for human consumption. The arguments // are for later consumption, allowing the message to be localized at a later // time. The passed argument list should not be modified. func NewMessagef(format string, args ...interface{}) Message { if false { // Let go vet know that we're expecting printf-like arguments. _ = fmt.Sprintf(format, args...) } return Message{format: format, args: args} } // NewMessage creates an error message for human consumption. // // Deprecated: Use [NewMessagef] instead. func NewMessage(format string, args []interface{}) Message { return NewMessagef(format, args...) } // Msg returns a printf-style format string and its arguments for human // consumption. func (m *Message) Msg() (format string, args []interface{}) { return m.format, m.args } func (m *Message) Error() string { return fmt.Sprintf(m.format, m.args...) } // Error is the common error message. type Error interface { // Position returns the primary position of an error. If multiple positions // contribute equally, this reflects one of them. Position() token.Pos // InputPositions reports positions that contributed to an error, including // the expressions resulting in the conflict, as well as values that were // the input to this expression. InputPositions() []token.Pos // Error reports the error message without position information. Error() string // Path returns the path into the data tree where the error occurred. // This path may be nil if the error is not associated with such a location. Path() []string // Msg returns the unformatted error message and its arguments for human // consumption. Msg() (format string, args []interface{}) } // Positions returns all positions returned by an error, sorted // by relevance when possible and with duplicates removed. func Positions(err error) []token.Pos { e := Error(nil) if !errors.As(err, &e) { return nil } a := make([]token.Pos, 0, 3) pos := e.Position() if pos.IsValid() { a = append(a, pos) } sortOffset := len(a) for _, p := range e.InputPositions() { if p.IsValid() && p != pos { a = append(a, p) } } slices.SortFunc(a[sortOffset:], comparePosWithNoPosFirst) return slices.Compact(a) } // comparePosWithNoPosFirst wraps [token.Pos.Compare] to place [token.NoPos] first, // which is currently required for errors to be sorted correctly. // TODO: give all errors valid positions so that we can use the standard sorting directly. func comparePosWithNoPosFirst(a, b token.Pos) int { if a == b { return 0 } else if a == token.NoPos { return -1 } else if b == token.NoPos { return +1 } return token.Pos.Compare(a, b) } // Path returns the path of an Error if err is of that type. func Path(err error) []string { if e := Error(nil); errors.As(err, &e) { return e.Path() } return nil } // Newf creates an Error with the associated position and message. func Newf(p token.Pos, format string, args ...interface{}) Error { return &posError{ pos: p, Message: NewMessagef(format, args...), } } // Wrapf creates an Error with the associated position and message. The provided // error is added for inspection context. func Wrapf(err error, p token.Pos, format string, args ...interface{}) Error { pErr := &posError{ pos: p, Message: NewMessagef(format, args...), } return Wrap(pErr, err) } // Wrap creates a new error where child is a subordinate error of parent. // If child is list of Errors, the result will itself be a list of errors // where child is a subordinate error of each parent. func Wrap(parent Error, child error) Error { if child == nil { return parent } a, ok := child.(list) if !ok { return &wrapped{parent, child} } b := make(list, len(a)) for i, err := range a { b[i] = &wrapped{parent, err} } return b } type wrapped struct { main Error wrap error } // Error implements the error interface. func (e *wrapped) Error() string { switch msg := e.main.Error(); { case e.wrap == nil: return msg case msg == "": return e.wrap.Error() default: return fmt.Sprintf("%s: %s", msg, e.wrap) } } func (e *wrapped) Is(target error) bool { return Is(e.main, target) } func (e *wrapped) As(target interface{}) bool { return As(e.main, target) } func (e *wrapped) Msg() (format string, args []interface{}) { return e.main.Msg() } func (e *wrapped) Path() []string { if p := e.main.Path(); p != nil { return p } return Path(e.wrap) } func (e *wrapped) InputPositions() []token.Pos { return append(e.main.InputPositions(), Positions(e.wrap)...) } func (e *wrapped) Position() token.Pos { if p := e.main.Position(); p != token.NoPos { return p } if wrap, ok := e.wrap.(Error); ok { return wrap.Position() } return token.NoPos } func (e *wrapped) Unwrap() error { return e.wrap } func (e *wrapped) Cause() error { return e.wrap } // Promote converts a regular Go error to an Error if it isn't already one. func Promote(err error, msg string) Error { switch x := err.(type) { case Error: return x default: return Wrapf(err, token.NoPos, "%s", msg) } } var _ Error = &posError{} // In an List, an error is represented by an *posError. // The position Pos, if valid, points to the beginning of // the offending token, and the error condition is described // by Msg. type posError struct { pos token.Pos Message } func (e *posError) Path() []string { return nil } func (e *posError) InputPositions() []token.Pos { return nil } func (e *posError) Position() token.Pos { return e.pos } // Append combines two errors, flattening Lists as necessary. func Append(a, b Error) Error { switch x := a.(type) { case nil: return b case list: return appendToList(x, b) } // Preserve order of errors. return appendToList(list{a}, b) } // Errors reports the individual errors associated with an error, which is // the error itself if there is only one or, if the underlying type is List, // its individual elements. If the given error is not an Error, it will be // promoted to one. func Errors(err error) []Error { if err == nil { return nil } var listErr list var errorErr Error switch { case As(err, &listErr): return listErr case As(err, &errorErr): return []Error{errorErr} default: return []Error{Promote(err, "")} } } func appendToList(a list, err Error) list { switch x := err.(type) { case nil: return a case list: if len(a) == 0 { return x } for _, e := range x { a = appendToList(a, e) } return a default: for _, e := range a { if e == err { return a } } return append(a, err) } } // list is a list of Errors. // The zero value for an list is an empty list ready to use. type list []Error func (p list) Is(target error) bool { for _, e := range p { if errors.Is(e, target) { return true } } return false } func (p list) As(target interface{}) bool { for _, e := range p { if errors.As(e, target) { return true } } return false } // AddNewf adds an Error with given position and error message to an List. func (p *list) AddNewf(pos token.Pos, msg string, args ...interface{}) { err := &posError{pos: pos, Message: Message{format: msg, args: args}} *p = append(*p, err) } // Add adds an Error with given position and error message to an List. func (p *list) Add(err Error) { *p = appendToList(*p, err) } // Reset resets an List to no errors. func (p *list) Reset() { *p = (*p)[:0] } // Sanitize sorts multiple errors and removes duplicates on a best effort basis. // If err represents a single or no error, it returns the error as is. func Sanitize(err Error) Error { if err == nil { return nil } if l, ok := err.(list); ok { a := l.sanitize() if len(a) == 1 { return a[0] } return a } return err } func (p list) sanitize() list { if p == nil { return p } a := slices.Clone(p) a.RemoveMultiples() return a } // Sort sorts an List. *posError entries are sorted by position, // other errors are sorted by error message, and before any *posError // entry. func (p list) Sort() { slices.SortFunc(p, func(a, b Error) int { if c := comparePosWithNoPosFirst(a.Position(), b.Position()); c != 0 { return c } if c := slices.Compare(a.Path(), b.Path()); c != 0 { return c } return cmp.Compare(a.Error(), b.Error()) }) } // RemoveMultiples sorts an List and removes all but the first error per line. func (p *list) RemoveMultiples() { p.Sort() var last Error i := 0 for _, e := range *p { if last == nil || !approximateEqual(last, e) { last = e (*p)[i] = e i++ } } (*p) = (*p)[0:i] } func approximateEqual(a, b Error) bool { aPos := a.Position() bPos := b.Position() if aPos == token.NoPos || bPos == token.NoPos { return a.Error() == b.Error() } return comparePosWithNoPosFirst(aPos, bPos) == 0 && slices.Compare(a.Path(), b.Path()) == 0 } // An List implements the error interface. func (p list) Error() string { format, args := p.Msg() return fmt.Sprintf(format, args...) } // Msg reports the unformatted error message for the first error, if any. func (p list) Msg() (format string, args []interface{}) { switch len(p) { case 0: return "no errors", nil case 1: return p[0].Msg() } return "%s (and %d more errors)", []interface{}{p[0], len(p) - 1} } // Position reports the primary position for the first error, if any. func (p list) Position() token.Pos { if len(p) == 0 { return token.NoPos } return p[0].Position() } // InputPositions reports the input positions for the first error, if any. func (p list) InputPositions() []token.Pos { if len(p) == 0 { return nil } return p[0].InputPositions() } // Path reports the path location of the first error, if any. func (p list) Path() []string { if len(p) == 0 { return nil } return p[0].Path() } // Err returns an error equivalent to this error list. // If the list is empty, Err returns nil. func (p list) Err() error { if len(p) == 0 { return nil } return p } // A Config defines parameters for printing. type Config struct { // Format formats the given string and arguments and writes it to w. // It is used for all printing. Format func(w io.Writer, format string, args ...interface{}) // Cwd is the current working directory. Filename positions are taken // relative to this path. Cwd string // ToSlash sets whether to use Unix paths. Mostly used for testing. ToSlash bool } // Print is a utility function that prints a list of errors to w, // one error per line, if the err parameter is an List. Otherwise // it prints the err string. func Print(w io.Writer, err error, cfg *Config) { if cfg == nil { cfg = &Config{} } for _, e := range list(Errors(err)).sanitize() { printError(w, e, cfg) } } // Details is a convenience wrapper for Print to return the error text as a // string. func Details(err error, cfg *Config) string { var b strings.Builder Print(&b, err, cfg) return b.String() } // String generates a short message from a given Error. func String(err Error) string { var b strings.Builder writeErr(&b, err) return b.String() } func writeErr(w io.Writer, err Error) { if path := strings.Join(err.Path(), "."); path != "" { _, _ = io.WriteString(w, path) _, _ = io.WriteString(w, ": ") } for { u := errors.Unwrap(err) msg, args := err.Msg() n, _ := fmt.Fprintf(w, msg, args...) if u == nil { break } if n > 0 { _, _ = io.WriteString(w, ": ") } err, _ = u.(Error) if err == nil { fmt.Fprint(w, u) break } } } func defaultFprintf(w io.Writer, format string, args ...interface{}) { fmt.Fprintf(w, format, args...) } func printError(w io.Writer, err error, cfg *Config) { if err == nil { return } fprintf := cfg.Format if fprintf == nil { fprintf = defaultFprintf } if e, ok := err.(Error); ok { writeErr(w, e) } else { fprintf(w, "%v", err) } positions := Positions(err) if len(positions) == 0 { fprintf(w, "\n") return } fprintf(w, ":\n") for _, p := range positions { pos := p.Position() path := pos.Filename if cfg.Cwd != "" { if p, err := filepath.Rel(cfg.Cwd, path); err == nil { path = p // Some IDEs (e.g. VSCode) only recognize a path if it starts // with a dot. This also helps to distinguish between local // files and builtin packages. if !strings.HasPrefix(path, ".") { path = fmt.Sprintf(".%c%s", filepath.Separator, path) } } } if cfg.ToSlash { path = filepath.ToSlash(path) } fprintf(w, " %s", path) if pos.IsValid() { if path != "" { fprintf(w, ":") } fprintf(w, "%d:%d", pos.Line, pos.Column) } fprintf(w, "\n") } } cue-lang-cue-db9cc73/cue/errors/errors_test.go000066400000000000000000000067131474664451600215010ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package errors import ( "bytes" "fmt" "testing" "cuelang.org/go/cue/token" ) func TestError_Error(t *testing.T) { tests := []struct { name string e Error want string }{ // TODO: Add test cases. } for _, tt := range tests { if got := tt.e.Error(); got != tt.want { t.Errorf("%q. Error.Error() = %v, want %v", tt.name, got, tt.want) } } } func TestErrorList_Add(t *testing.T) { type args struct { pos token.Pos msg string } tests := []struct { name string p *list args args }{ // TODO: Add test cases. } for _, tt := range tests { tt.p.AddNewf(tt.args.pos, tt.args.msg) } } func TestErrorList_Reset(t *testing.T) { tests := []struct { name string p *list }{ // TODO: Add test cases. } for _, tt := range tests { tt.p.Reset() } } func TestErrorList_Sort(t *testing.T) { tests := []struct { name string p list }{ // TODO: Add test cases. } for _, tt := range tests { tt.p.Sort() } } func TestErrorList_RemoveMultiples(t *testing.T) { tests := []struct { name string p *list }{ // TODO: Add test cases. } for _, tt := range tests { tt.p.RemoveMultiples() } } func TestErrorList_Error(t *testing.T) { tests := []struct { name string p list want string }{ // TODO: Add test cases. } for _, tt := range tests { if got := tt.p.Error(); got != tt.want { t.Errorf("%q. list.Error() = %v, want %v", tt.name, got, tt.want) } } } func TestErrorList_Err(t *testing.T) { tests := []struct { name string p list wantErr bool }{ // TODO: Add test cases. } for _, tt := range tests { if err := tt.p.Err(); (err != nil) != tt.wantErr { t.Errorf("%q. list.Err() error = %v, wantErr %v", tt.name, err, tt.wantErr) } } } func TestPrintError(t *testing.T) { tests := []struct { name string err error wantW string }{{ name: "SimplePromoted", err: Promote(fmt.Errorf("hello"), "msg"), wantW: "msg: hello\n", }, { name: "PromoteWithPercent", err: Promote(fmt.Errorf("hello"), "msg%s"), wantW: "msg%s: hello\n", }, { name: "PromoteWithEmptyString", err: Promote(fmt.Errorf("hello"), ""), wantW: "hello\n", }, { name: "TwoErrors", err: Append(Promote(fmt.Errorf("hello"), "x"), Promote(fmt.Errorf("goodbye"), "y")), wantW: "x: hello\ny: goodbye\n", }, { name: "WrappedSingle", err: fmt.Errorf("wrap: %w", Promote(fmt.Errorf("hello"), "x")), wantW: "x: hello\n", }, { name: "WrappedMultiple", err: fmt.Errorf("wrap: %w", Append(Promote(fmt.Errorf("hello"), "x"), Promote(fmt.Errorf("goodbye"), "y")), ), wantW: "x: hello\ny: goodbye\n", }} // TODO tests for errors with positions. for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := &bytes.Buffer{} Print(w, tt.err, nil) if gotW := w.String(); gotW != tt.wantW { t.Errorf("unexpected PrintError result\ngot %q\nwant %q", gotW, tt.wantW) } }) } } cue-lang-cue-db9cc73/cue/errors/example_test.go000066400000000000000000000043731474664451600216200ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package errors_test import ( "fmt" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" ) func Example() { v := cuecontext.New().CompileString(` a: string & 123 b: int & "foo" `, cue.Filename("input.cue")) err := v.Validate() // [error.Error] only shows the first error encountered. fmt.Printf("string via the Error method:\n %q\n\n", err.Error()) // [errors.Errors] allows listing all the errors encountered. fmt.Printf("list via errors.Errors:\n") for _, e := range errors.Errors(err) { fmt.Printf(" * %s\n", e) } fmt.Printf("\n") // [errors.Positions] lists the positions of all errors encountered. fmt.Printf("positions via errors.Positions:\n") for _, pos := range errors.Positions(err) { fmt.Printf(" * %s\n", pos) } fmt.Printf("\n") // [errors.Details] renders a human-friendly description of all errors like cmd/cue does. fmt.Printf("human-friendly string via errors.Details:\n") fmt.Println(errors.Details(err, nil)) // Output: // string via the Error method: // "a: conflicting values string and 123 (mismatched types string and int) (and 1 more errors)" // // list via errors.Errors: // * a: conflicting values string and 123 (mismatched types string and int) // * b: conflicting values int and "foo" (mismatched types int and string) // // positions via errors.Positions: // * input.cue:2:6 // * input.cue:2:15 // // human-friendly string via errors.Details: // a: conflicting values string and 123 (mismatched types string and int): // input.cue:2:6 // input.cue:2:15 // b: conflicting values int and "foo" (mismatched types int and string): // input.cue:3:6 // input.cue:3:12 } cue-lang-cue-db9cc73/cue/examplecompile_test.go000066400000000000000000000025131474664451600216470ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "log" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" ) func ExampleContext() { ctx := cuecontext.New() v := ctx.CompileString(` a: 2 b: 3 "a+b": a + b `) if err := v.Err(); err != nil { log.Fatal(err) } p("lookups") p("a: %v", v.LookupPath(cue.ParsePath("a"))) p("b: %v", v.LookupPath(cue.ParsePath("b"))) p(`"a+b": %v`, v.LookupPath(cue.ParsePath(`"a+b"`))) p("") p("expressions") p("a + b: %v", ctx.CompileString("a + b", cue.Scope(v))) p("a * b: %v", ctx.CompileString("a * b", cue.Scope(v))) // Output: // lookups // a: 2 // b: 3 // "a+b": 5 // // expressions // a + b: 5 // a * b: 6 } func p(format string, args ...interface{}) { fmt.Printf(format+"\n", args...) } cue-lang-cue-db9cc73/cue/examples_test.go000066400000000000000000000067721474664451600204740ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "log" "os" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/internal/cuetxtar" "golang.org/x/tools/txtar" ) func load(file string) *cue.Instance { dir, _ := os.MkdirTemp("", "*") defer os.RemoveAll(dir) inst := cue.Build(cuetxtar.Load(txtar.Parse([]byte(file)), dir))[0] if err := inst.Err; err != nil { panic(err) } return inst } func ExampleHid() { const file = ` -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- main.cue -- import "mod.test/foo:bar" bar _foo: int // scoped in main (anonymous) package baz: _foo -- foo/bar.cue -- package bar _foo: int // scoped within imported package bar: _foo ` v := load(file).Value() v = v.FillPath(cue.MakePath(cue.Hid("_foo", "mod.test/foo:bar")), 1) v = v.FillPath(cue.MakePath(cue.Hid("_foo", "_")), 2) fmt.Println(v.LookupPath(cue.ParsePath("bar")).Int64()) fmt.Println(v.LookupPath(cue.ParsePath("baz")).Int64()) // Output: // 1 // 2 } func ExampleValue_Allows() { ctx := cuecontext.New() const file = ` a: [1, 2, ...int] b: #Point #Point: { x: int y: int z?: int } c: [string]: int d: #C #C: [>"m"]: int ` v := ctx.CompileString(file) if err := v.Err(); err != nil { log.Fatal(err) } a := v.LookupPath(cue.ParsePath("a")) fmt.Println("a allows:") fmt.Println(" index 4: ", a.Allows(cue.Index(4))) fmt.Println(" any index: ", a.Allows(cue.AnyIndex)) fmt.Println(" any string: ", a.Allows(cue.AnyString)) b := v.LookupPath(cue.ParsePath("b")) fmt.Println("b allows:") fmt.Println(" field x: ", b.Allows(cue.Str("x"))) fmt.Println(" field z: ", b.Allows(cue.Str("z"))) fmt.Println(" field foo: ", b.Allows(cue.Str("foo"))) fmt.Println(" index 4: ", b.Allows(cue.Index(4))) fmt.Println(" any string: ", b.Allows(cue.AnyString)) c := v.LookupPath(cue.ParsePath("c")) fmt.Println("c allows:") fmt.Println(" field z: ", c.Allows(cue.Str("z"))) fmt.Println(" field foo: ", c.Allows(cue.Str("foo"))) fmt.Println(" index 4: ", c.Allows(cue.Index(4))) fmt.Println(" any string: ", c.Allows(cue.AnyString)) d := v.LookupPath(cue.ParsePath("d")) fmt.Println("d allows:") fmt.Println(" field z: ", d.Allows(cue.Str("z"))) fmt.Println(" field foo: ", d.Allows(cue.Str("foo"))) fmt.Println(" index 4: ", d.Allows(cue.Index(4))) fmt.Println(" any string: ", d.Allows(cue.AnyString)) // Output: // a allows: // index 4: true // any index: true // any string: false // b allows: // field x: true // field z: true // field foo: false // index 4: false // any string: false // c allows: // field z: true // field foo: true // index 4: false // any string: true // d allows: // field z: true // field foo: false // index 4: false // any string: false } cue-lang-cue-db9cc73/cue/export_test.go000066400000000000000000000020031474664451600201560ustar00rootroot00000000000000// Copyright 2024 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import "cuelang.org/go/internal/core/adt" // Export the private Value.v field for testing purposes. But do so as // a function, not a method, so that we don't run the risk of // accidentally extending the set of types Value may inhabit during // tests. func ValueVertex(v Value) *adt.Vertex { return v.v } var ( ValueCtx = Value.ctx AnyDefinition = anyDefinition DebugStr = debugStr PathToStrings = pathToStrings ) cue-lang-cue-db9cc73/cue/format.go000066400000000000000000000112451474664451600170760ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "bytes" "fmt" "math/big" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/format" "cuelang.org/go/internal/core/export" ) // TODO: // * allow '-' to strip outer curly braces? // - simplify output; can be used in combination with other flags // * advertise: // c like v, but print comments // a like c, but print attributes and package-local hidden fields as well // Format prints a CUE value. // // WARNING: although we are narrowing down the semantics, the verbs and options // are still subject to change. this API is experimental although it is likely // getting close to the final design. // // It recognizes the following verbs: // // v print CUE value // // The verbs support the following flags: // // # print as schema and include definitions. // The result is printed as a self-contained file, instead of an the // expression format. // + evaluate: resolve defaults and error on incomplete errors // // Indentation can be controlled as follows: // // width indent the cue block by tab stops (e.g. %2v) // precision convert tabs to spaces (e.g. %.2v), where // a value of 0 means no indentation or newlines (TODO). // // If the value kind corresponds to one of the following Go types, the // usual Go formatting verbs for that type can be used: // // Int: b,d,o,O,q,x,X // Float: f,e,E,g,G // String/Bytes: s,q,x,X // // The %v directive will be used if the type is not supported for that verb. func (v Value) Format(state fmt.State, verb rune) { if v.v == nil { fmt.Fprint(state, "") return } switch verb { case 'a': formatCUE(state, v, true, true) case 'c': formatCUE(state, v, true, false) case 'v': formatCUE(state, v, false, false) case 'd', 'o', 'O', 'U': var i big.Int if _, err := v.Int(&i); err != nil { formatCUE(state, v, false, false) return } i.Format(state, verb) case 'f', 'e', 'E', 'g', 'G': d, err := v.Decimal() if err != nil { formatCUE(state, v, false, false) return } d.Format(state, verb) case 's', 'q': // TODO: this drops other formatting directives msg := "%s" if verb == 'q' { msg = "%q" } if b, err := v.Bytes(); err == nil { fmt.Fprintf(state, msg, b) } else { s := fmt.Sprintf("%+v", v) fmt.Fprintf(state, msg, s) } case 'x', 'X': switch v.Kind() { case StringKind, BytesKind: b, _ := v.Bytes() // TODO: this drops other formatting directives msg := "%x" if verb == 'X' { msg = "%X" } fmt.Fprintf(state, msg, b) case IntKind, NumberKind: var i big.Int _, _ = v.Int(&i) i.Format(state, verb) case FloatKind: dec, _ := v.Decimal() dec.Format(state, verb) default: formatCUE(state, v, false, false) } default: formatCUE(state, v, false, false) } } func formatCUE(state fmt.State, v Value, showDocs, showAll bool) { pkgPath := v.instance().ID() p := *export.Simplified isDef := false switch { case state.Flag('#'): isDef = true p = export.Profile{ ShowOptional: true, ShowDefinitions: true, ShowHidden: true, } case state.Flag('+'): p = *export.Final fallthrough default: p.ShowHidden = showAll } p.ShowDocs = showDocs p.ShowAttributes = showAll var n ast.Node if isDef { n, _ = p.Def(v.idx, pkgPath, v.v) } else { n, _ = p.Value(v.idx, pkgPath, v.v) } formatExpr(state, n) } func formatExpr(state fmt.State, n ast.Node) { opts := make([]format.Option, 0, 3) if state.Flag('-') { opts = append(opts, format.Simplify()) } // TODO: handle verbs to allow formatting based on type: if width, ok := state.Width(); ok { opts = append(opts, format.IndentPrefix(width)) } // TODO: consider this: should tabs or spaces be the default? if tabwidth, ok := state.Precision(); ok { // TODO: 0 means no newlines. opts = append(opts, format.UseSpaces(tabwidth), format.TabIndent(false)) } // TODO: consider this. // else if state.Flag(' ') { // opts = append(opts, // format.UseSpaces(4), // format.TabIndent(false)) // } b, _ := format.Node(n, opts...) b = bytes.Trim(b, "\n\r") _, _ = state.Write(b) } cue-lang-cue-db9cc73/cue/format/000077500000000000000000000000001474664451600165445ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/format/format.go000066400000000000000000000204451474664451600203700ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package format implements standard formatting of CUE configurations. package format // TODO: this package is in need of a rewrite. When doing so, the API should // allow for reformatting an AST, without actually writing bytes. // // In essence, formatting determines the relative spacing to tokens. It should // be possible to have an abstract implementation providing such information // that can be used to either format or update an AST in a single walk. import ( "bytes" "fmt" "text/tabwriter" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" ) // An Option sets behavior of the formatter. type Option func(c *config) // Simplify allows the formatter to simplify output, such as removing // unnecessary quotes. func Simplify() Option { return func(c *config) { c.simplify = true } } // UseSpaces specifies that tabs should be converted to spaces and sets the // default tab width. func UseSpaces(tabwidth int) Option { return func(c *config) { c.UseSpaces = true c.Tabwidth = tabwidth } } // TabIndent specifies whether to use tabs for indentation independent of // UseSpaces. func TabIndent(indent bool) Option { return func(c *config) { c.TabIndent = indent } } // IndentPrefix specifies the number of tabstops to use as a prefix for every // line. func IndentPrefix(n int) Option { return func(c *config) { c.Indent = n } } // TODO: make public // sortImportsOption causes import declarations to be sorted. func sortImportsOption() Option { return func(c *config) { c.sortImports = true } } // TODO: other options: // // const ( // RawFormat Mode = 1 << iota // do not use a tabwriter; if set, UseSpaces is ignored // TabIndent // use tabs for indentation independent of UseSpaces // UseSpaces // use spaces instead of tabs for alignment // SourcePos // emit //line comments to preserve original source positions // ) // Node formats node in canonical cue fmt style and writes the result to dst. // // The node type must be [*ast.File], [][ast.Decl], [ast.Expr], [ast.Decl], or // [ast.Spec]. Node does not modify node. Imports are not sorted for nodes // representing partial source files (for instance, if the node is not an // *ast.File). // // The function may return early (before the entire result is written) and // return a formatting error, for instance due to an incorrect AST. func Node(node ast.Node, opt ...Option) ([]byte, error) { cfg := newConfig(opt) return cfg.fprint(node) } // Source formats src in canonical cue fmt style and returns the result or an // (I/O or syntax) error. src is expected to be a syntactically correct CUE // source file, or a list of CUE declarations or statements. // // If src is a partial source file, the leading and trailing space of src is // applied to the result (such that it has the same leading and trailing space // as src), and the result is indented by the same amount as the first line of // src containing code. Imports are not sorted for partial source files. // // Caution: Tools relying on consistent formatting based on the installed // version of cue (for instance, such as for presubmit checks) should execute // that cue binary instead of calling Source. func Source(b []byte, opt ...Option) ([]byte, error) { cfg := newConfig(opt) f, err := parser.ParseFile("", b, parser.ParseComments) if err != nil { return nil, fmt.Errorf("parse: %s", err) } // print AST return cfg.fprint(f) } type config struct { UseSpaces bool TabIndent bool Tabwidth int // default: 4 Indent int // default: 0 (all code is indented at least by this much) simplify bool sortImports bool } func newConfig(opt []Option) *config { cfg := &config{ Tabwidth: 8, TabIndent: true, UseSpaces: true, } for _, o := range opt { o(cfg) } return cfg } // Config defines the output of Fprint. func (cfg *config) fprint(node interface{}) (out []byte, err error) { var p printer p.init(cfg) if err = printNode(node, &p); err != nil { return p.output, err } padchar := byte('\t') if cfg.UseSpaces { padchar = byte(' ') } twmode := tabwriter.StripEscape | tabwriter.TabIndent | tabwriter.DiscardEmptyColumns if cfg.TabIndent { twmode |= tabwriter.TabIndent } buf := &bytes.Buffer{} tw := tabwriter.NewWriter(buf, 0, cfg.Tabwidth, 1, padchar, twmode) // write printer result via tabwriter/trimmer to output if _, err = tw.Write(p.output); err != nil { return } err = tw.Flush() if err != nil { return buf.Bytes(), err } b := buf.Bytes() if !cfg.TabIndent { b = bytes.ReplaceAll(b, []byte{'\t'}, bytes.Repeat([]byte{' '}, cfg.Tabwidth)) } return b, nil } // A formatter walks an [ast.Node], interspersed with comments and spacing // directives, in the order that they would occur in printed form. type formatter struct { *printer stack []frame current frame nestExpr int } func newFormatter(p *printer) *formatter { f := &formatter{ printer: p, current: frame{ settings: settings{ nodeSep: newline, parentSep: newline, }, }, } return f } type whiteSpace int const ( _ whiteSpace = 0 // write a space, or disallow it blank whiteSpace = 1 << iota vtab // column marker noblank nooverride comma // print a comma, unless trailcomma overrides it trailcomma // print a trailing comma unless closed on same line declcomma // write a comma when not at the end of line newline // write a line in a table formfeed // next line is not part of the table newsection // add two newlines indent // request indent an extra level after the next newline unindent // unindent a level after the next newline indented // element was indented. ) type frame struct { cg []*ast.CommentGroup pos int8 settings } type settings struct { // separator is blank if the current node spans a single line and newline // otherwise. nodeSep whiteSpace parentSep whiteSpace override whiteSpace } // suppress spurious linter warning: field is actually used. func init() { s := settings{} _ = s.override } func (f *formatter) print(a ...interface{}) { for _, x := range a { f.Print(x) switch x.(type) { case string, token.Token: // , *ast.BasicLit, *ast.Ident: f.current.pos++ } } } func (f *formatter) formfeed() whiteSpace { if f.current.nodeSep == blank { return blank } return formfeed } func (f *formatter) onOneLine(node ast.Node) bool { a := node.Pos() b := node.End() if a.IsValid() && b.IsValid() { return f.lineFor(a) == f.lineFor(b) } // TODO: walk and look at relative positions to determine the same? return false } func (f *formatter) before(node ast.Node) bool { f.stack = append(f.stack, f.current) f.current = frame{settings: f.current.settings} f.current.parentSep = f.current.nodeSep if node != nil { s, ok := node.(*ast.StructLit) if ok && len(s.Elts) <= 1 && f.current.nodeSep != blank && f.onOneLine(node) { f.current.nodeSep = blank } f.current.cg = ast.Comments(node) f.visitComments(f.current.pos) return true } return false } func (f *formatter) after(node ast.Node) { f.visitComments(127) p := len(f.stack) - 1 f.current = f.stack[p] f.stack = f.stack[:p] f.current.pos++ f.visitComments(f.current.pos) } func (f *formatter) visitComments(until int8) { c := &f.current printed := false for ; len(c.cg) > 0 && c.cg[0].Position <= until; c.cg = c.cg[1:] { if printed { f.Print(newsection) } printed = true f.printComment(c.cg[0]) } } func (f *formatter) printComment(cg *ast.CommentGroup) { f.Print(cg) if cg.Doc && len(f.output) > 0 { f.Print(newline) } for _, c := range cg.List { if f.pos.Column > 1 { // Vertically align inline comments. f.Print(vtab) } f.Print(c.Slash) f.Print(c) f.printingComment = true f.Print(newline) if cg.Doc { f.Print(nooverride) } } } cue-lang-cue-db9cc73/cue/format/format_test.go000066400000000000000000000206171474664451600214300ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package format // TODO: port more of the tests of go/printer import ( "io/fs" "os" "path" "path/filepath" "strings" "testing" "github.com/go-quicktest/qt" "golang.org/x/tools/txtar" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/cuetest" ) var ( defaultConfig = newConfig([]Option{}) Fprint = defaultConfig.fprint ) func TestFiles(t *testing.T) { txtarFiles, err := filepath.Glob("testdata/*.txtar") qt.Assert(t, qt.IsNil(err)) for _, txtarFile := range txtarFiles { ar, err := txtar.ParseFile(txtarFile) qt.Assert(t, qt.IsNil(err)) opts := []Option{TabIndent(true)} for _, word := range strings.Fields(string(ar.Comment)) { switch word { case "simplify": opts = append(opts, Simplify()) case "sort-imports": opts = append(opts, sortImportsOption()) } } tfs, err := txtar.FS(ar) qt.Assert(t, qt.IsNil(err)) inputFiles, err := fs.Glob(tfs, "*.input") qt.Assert(t, qt.IsNil(err)) for _, inputFile := range inputFiles { goldenFile := strings.TrimSuffix(inputFile, ".input") + ".golden" t.Run(path.Join(txtarFile, inputFile), func(t *testing.T) { src, err := fs.ReadFile(tfs, inputFile) qt.Assert(t, qt.IsNil(err)) res, err := Source(src, opts...) qt.Assert(t, qt.IsNil(err)) // make sure formatted output is syntactically correct _, err = parser.ParseFile("", res, parser.AllErrors) qt.Assert(t, qt.IsNil(err)) // update golden files if necessary // TODO(mvdan): deduplicate this code with UpdateGoldenFiles on txtar files? if cuetest.UpdateGoldenFiles { for i := range ar.Files { file := &ar.Files[i] if file.Name == goldenFile { file.Data = res return } } ar.Files = append(ar.Files, txtar.File{ Name: goldenFile, Data: res, }) return } // get golden gld, err := fs.ReadFile(tfs, goldenFile) qt.Assert(t, qt.IsNil(err)) // formatted source and golden must be the same qt.Assert(t, qt.Equals(string(res), string(gld))) // TODO(mvdan): check that all files format in an idempotent way, // i.e. that formatting a golden file results in no changes. }) } if cuetest.UpdateGoldenFiles { err = os.WriteFile(txtarFile, txtar.Format(ar), 0o666) qt.Assert(t, qt.IsNil(err)) } } } // Verify that the printer can be invoked during initialization. func init() { const name = "foobar" b, err := Fprint(&ast.Ident{Name: name}) if err != nil { panic(err) // error in test } // in debug mode, the result contains additional information; // ignore it if s := string(b); !debug && s != name { panic("got " + s + ", want " + name) } } // TestNodes tests nodes that are invalid CUE, but are accepted by // format. func TestNodes(t *testing.T) { testCases := []struct { name string in ast.Node out string }{{ name: "old-style octal numbers", in: ast.NewLit(token.INT, "0123"), out: "0o123", }, { name: "labels with multi-line strings", in: &ast.Field{ Label: ast.NewLit(token.STRING, `""" foo bar """`, ), Value: ast.NewIdent("goo"), }, out: `"foo\nbar": goo`, }, { name: "foo", in: func() ast.Node { st := ast.NewStruct("version", ast.NewString("foo")) st = ast.NewStruct("info", st) ast.AddComment(st.Elts[0], internal.NewComment(true, "FOO")) return st }(), out: `{ // FOO info: { version: "foo" } }`, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { b, err := Node(tc.in, Simplify()) if err != nil { t.Fatal(err) } if got := string(b); got != tc.out { t.Errorf("\ngot: %v; want: %v", got, tc.out) } }) } } // Verify that the printer doesn't crash if the AST contains Bad... nodes. func TestBadNodes(t *testing.T) { const src = "package p\n(" const res = "package p\n\n(_|_)\n" f, err := parser.ParseFile("", src, parser.ParseComments) if err == nil { t.Error("expected illegal program") // error in test } b, _ := Fprint(f) if string(b) != res { t.Errorf("got %q, expected %q", string(b), res) } } func TestPackage(t *testing.T) { f := &ast.File{ Decls: []ast.Decl{ &ast.Package{Name: ast.NewIdent("foo")}, &ast.EmbedDecl{ Expr: &ast.BasicLit{ Kind: token.INT, ValuePos: token.NoSpace.Pos(), Value: "1", }, }, }, } b, err := Node(f) if err != nil { t.Fatal(err) } const want = "package foo\n\n1\n" if got := string(b); got != want { t.Errorf("got %q, expected %q", got, want) } } // idents is an iterator that returns all idents in f via the result channel. func idents(f *ast.File) <-chan *ast.Ident { v := make(chan *ast.Ident) go func() { ast.Walk(f, func(n ast.Node) bool { if ident, ok := n.(*ast.Ident); ok { v <- ident } return true }, nil) close(v) }() return v } // identCount returns the number of identifiers found in f. func identCount(f *ast.File) int { n := 0 for range idents(f) { n++ } return n } // Verify that the SourcePos mode emits correct //line comments // by testing that position information for matching identifiers // is maintained. func TestSourcePos(t *testing.T) { const src = `package p import ( "go/printer" "math" "regexp" ) let pi = 3.14 let xx = 0 t: { x: int y: int z: int u: number v: number w: number } e: a*t.x + b*t.y // two extra lines here // ... e2: c*t.z ` // parse original f1, err := parser.ParseFile("src", src, parser.ParseComments) if err != nil { t.Fatal(err) } // pretty-print original b, err := (&config{UseSpaces: true, Tabwidth: 8}).fprint(f1) if err != nil { t.Fatal(err) } // parse pretty printed original // (//line comments must be interpreted even w/o parser.ParseComments set) f2, err := parser.ParseFile("", b, parser.AllErrors, parser.ParseComments) if err != nil { t.Fatalf("%s\n%s", err, b) } // At this point the position information of identifiers in f2 should // match the position information of corresponding identifiers in f1. // number of identifiers must be > 0 (test should run) and must match n1 := identCount(f1) n2 := identCount(f2) if n1 == 0 { t.Fatal("got no idents") } if n2 != n1 { t.Errorf("got %d idents; want %d", n2, n1) } // verify that all identifiers have correct line information i2range := idents(f2) for i1 := range idents(f1) { i2 := <-i2range if i2 == nil || i1 == nil { t.Fatal("non nil identifiers") } if i2.Name != i1.Name { t.Errorf("got ident %s; want %s", i2.Name, i1.Name) } l1 := i1.Pos().Line() l2 := i2.Pos().Line() if l2 != l1 { t.Errorf("got line %d; want %d for %s", l2, l1, i1.Name) } } if t.Failed() { t.Logf("\n%s", b) } } var decls = []string{ "package p\n\n" + `import "fmt"`, "package p\n\n" + "let pi = 3.1415\nlet e = 2.71828\n\nlet x = pi", } func TestDeclLists(t *testing.T) { for _, src := range decls { file, err := parser.ParseFile("", src, parser.ParseComments) if err != nil { panic(err) // error in test } b, err := Fprint(file.Decls) // only print declarations if err != nil { panic(err) // error in test } out := string(b) if out != src { t.Errorf("\ngot : %q\nwant: %q\n", out, src) } } } func TestIncorrectIdent(t *testing.T) { testCases := []struct { ident string out string }{ {"foo", "foo"}, {"a.b.c", `"a.b.c"`}, {"for", "for"}, } for _, tc := range testCases { t.Run(tc.ident, func(t *testing.T) { b, _ := Node(&ast.Field{Label: ast.NewIdent(tc.ident), Value: ast.NewIdent("A")}) if got, want := string(b), tc.out+`: A`; got != want { t.Errorf("got %q; want %q", got, want) } }) } } // TextX is a skeleton test that can be filled in for debugging one-off cases. // Do not remove. func TestX(t *testing.T) { t.Skip() const src = ` ` b, err := Source([]byte(src), Simplify()) if err != nil { t.Error(err) } _ = b t.Error("\n", string(b)) } cue-lang-cue-db9cc73/cue/format/import.go000066400000000000000000000076501474664451600204150ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package format import ( "sort" "strconv" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/token" ) // sortImports sorts runs of consecutive import lines in import blocks in f. // It also removes duplicate imports when it is possible to do so without data // loss. func sortImports(d *ast.ImportDecl) { if !d.Lparen.IsValid() || len(d.Specs) == 0 { // Not a block: sorted by default. return } // Identify and sort runs of specs on successive lines. i := 0 specs := d.Specs[:0] for j, s := range d.Specs { if j > i && (s.Pos().RelPos() >= token.NewSection || hasDoc(s)) { setRelativePos(s, token.Newline) // j begins a new run. End this one. block := sortSpecs(d.Specs[i:j]) specs = append(specs, block...) i = j } } specs = append(specs, sortSpecs(d.Specs[i:])...) setRelativePos(specs[0], token.Newline) d.Specs = specs } func setRelativePos(s *ast.ImportSpec, r token.RelPos) { if hasDoc(s) { return } pos := s.Pos().WithRel(r) if s.Name != nil { s.Name.NamePos = pos } else { s.Path.ValuePos = pos } } func hasDoc(s *ast.ImportSpec) bool { for _, doc := range s.Comments() { if doc.Doc { return true } } return false } func importPath(s *ast.ImportSpec) string { t, err := strconv.Unquote(s.Path.Value) if err == nil { return t } return "" } func importName(s *ast.ImportSpec) string { n := s.Name if n == nil { return "" } return n.Name } func importComment(s *ast.ImportSpec) string { for _, c := range s.Comments() { if c.Line { return c.Text() } } return "" } // collapse indicates whether prev may be removed, leaving only next. func collapse(prev, next *ast.ImportSpec) bool { if importPath(next) != importPath(prev) || importName(next) != importName(prev) { return false } for _, c := range prev.Comments() { if !c.Doc { return false } } return true } type posSpan struct { Start token.Pos End token.Pos } func sortSpecs(specs []*ast.ImportSpec) []*ast.ImportSpec { // Can't short-circuit here even if specs are already sorted, // since they might yet need deduplication. // A lone import, however, may be safely ignored. if len(specs) <= 1 { setRelativePos(specs[0], token.NewSection) return specs } // Record positions for specs. pos := make([]posSpan, len(specs)) for i, s := range specs { pos[i] = posSpan{s.Pos(), s.End()} } // Sort the import specs by import path. // Remove duplicates, when possible without data loss. // Reassign the import paths to have the same position sequence. // Reassign each comment to abut the end of its spec. // Sort the comments by new position. sort.Sort(byImportSpec(specs)) // Dedup. Thanks to our sorting, we can just consider // adjacent pairs of imports. deduped := specs[:0] for i, s := range specs { if i == len(specs)-1 || !collapse(s, specs[i+1]) { deduped = append(deduped, s) } } specs = deduped setRelativePos(specs[0], token.NewSection) return specs } type byImportSpec []*ast.ImportSpec func (x byImportSpec) Len() int { return len(x) } func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x byImportSpec) Less(i, j int) bool { ipath := importPath(x[i]) jpath := importPath(x[j]) if ipath != jpath { return ipath < jpath } iname := importName(x[i]) jname := importName(x[j]) if iname != jname { return iname < jname } return importComment(x[i]) < importComment(x[j]) } cue-lang-cue-db9cc73/cue/format/node.go000066400000000000000000000521461474664451600200300ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package format import ( "fmt" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/token" "cuelang.org/go/internal" ) func printNode(node interface{}, f *printer) error { s := newFormatter(f) ls := labelSimplifier{scope: map[string]bool{}} // format node f.allowed = nooverride // gobble initial whitespace. switch x := node.(type) { case *ast.File: if f.cfg.simplify { ls.markReferences(x) } s.file(x) case ast.Expr: if f.cfg.simplify { ls.markReferences(x) } s.expr(x) case ast.Decl: if f.cfg.simplify { ls.markReferences(x) } s.decl(x) // case ast.Node: // TODO: do we need this? // s.walk(x) case []ast.Decl: if f.cfg.simplify { ls.processDecls(x) } s.walkDeclList(x) default: goto unsupported } return s.errs unsupported: return fmt.Errorf("cue/format: unsupported node type %T", node) } func isRegularField(tok token.Token) bool { return tok == token.ILLEGAL || tok == token.COLON } // Helper functions for common node lists. They may be empty. func nestDepth(f *ast.Field) int { d := 1 if s, ok := f.Value.(*ast.StructLit); ok { switch { case len(s.Elts) != 1: d = 0 default: if f, ok := s.Elts[0].(*ast.Field); ok { d += nestDepth(f) } } } return d } // TODO: be more accurate and move to astutil func hasDocComments(d ast.Decl) bool { if len(ast.Comments(d)) > 0 { return true } switch x := d.(type) { case *ast.Field: return len(ast.Comments(x.Label)) > 0 case *ast.Alias: return len(ast.Comments(x.Ident)) > 0 case *ast.LetClause: return len(ast.Comments(x.Ident)) > 0 } return false } func (f *formatter) walkDeclList(list []ast.Decl) { f.before(nil) d := 0 var ellipsis ast.Decl for i, x := range list { if i > 0 { f.print(declcomma) nd := 0 if f, ok := x.(*ast.Field); ok { nd = nestDepth(f) } if f.current.parentSep == newline && (d == 0 || nd != d) { f.print(f.formfeed()) } if hasDocComments(x) { switch x := list[i-1].(type) { case *ast.Field: if internal.IsDefinition(x.Label) { f.print(newsection) } default: f.print(newsection) } } } if f.printer.cfg.simplify && internal.IsEllipsis(x) { ellipsis = x continue } f.decl(x) d = 0 if f, ok := x.(*ast.Field); ok { d = nestDepth(f) } if j := i + 1; j < len(list) { switch x := list[j].(type) { case *ast.Field: switch x := x.Value.(type) { case *ast.StructLit: // TODO: not entirely correct: could have multiple elements, // not have a valid Lbrace, and be marked multiline. This // cannot occur for ASTs resulting from a parse, though. if x.Lbrace.IsValid() || len(x.Elts) != 1 { f.print(f.formfeed()) continue } case *ast.ListLit: f.print(f.formfeed()) continue } } } f.print(f.current.parentSep) } if ellipsis != nil { // ensure that comments associated with the original ellipsis are preserved n := &ast.Ellipsis{} ast.SetComments(n, ast.Comments(ellipsis)) f.decl(n) f.print(f.current.parentSep) } f.after(nil) } func (f *formatter) walkSpecList(list []*ast.ImportSpec) { f.before(nil) for _, x := range list { f.before(x) f.importSpec(x) f.after(x) } f.after(nil) } func (f *formatter) walkClauseList(list []ast.Clause, ws whiteSpace) { f.before(nil) for i, x := range list { f.before(x) // Only print the whitespace between the clauses. if i > 0 { f.print(ws) } f.clause(x) f.after(x) } f.after(nil) } func (f *formatter) walkListElems(list []ast.Expr) { f.before(nil) for _, x := range list { f.before(x) // This is a hack to ensure that comments are printed correctly in lists. // A comment must be printed after each element in a list, but we can't // print a comma at the end of a comment because it will be considered // part of the comment and ignored. // To fix this we collect all comments that appear after the element, // and only handle them after it's formatted. var commentsAfter []*ast.CommentGroup splitComments := x.Pos().IsValid() if splitComments { for _, cg := range ast.Comments(x) { if x.Pos().Before(cg.Pos()) { commentsAfter = append(commentsAfter, cg) } } } if splitComments { f.current.cg = nil } switch n := x.(type) { case *ast.Comprehension: f.walkClauseList(n.Clauses, blank) f.print(blank, nooverride) f.expr(n.Value) case *ast.Ellipsis: f.ellipsis(n) case *ast.Alias: f.expr(n.Ident) f.print(n.Equal, token.BIND) f.expr(n.Expr) // TODO: ast.CommentGroup: allows comment groups in ListLits. case ast.Expr: f.exprRaw(n, token.LowestPrec, 1) } f.print(comma, blank) if splitComments { f.current.cg = commentsAfter } f.after(x) } f.after(nil) } func (f *formatter) walkArgsList(list []ast.Expr, depth int) { f.before(nil) for _, x := range list { f.before(x) f.exprRaw(x, token.LowestPrec, depth) f.print(comma, blank) f.after(x) } f.after(nil) } func (f *formatter) file(file *ast.File) { f.before(file) f.walkDeclList(file.Decls) f.after(file) f.print(token.EOF) } func (f *formatter) inlineField(n *ast.Field) *ast.Field { regular := internal.IsRegularField(n) // shortcut single-element structs. // If the label has a valid position, we assume that an unspecified // Lbrace signals the intent to collapse fields. if !n.Label.Pos().IsValid() && !(f.printer.cfg.simplify && regular) { return nil } obj, ok := n.Value.(*ast.StructLit) if !ok || len(obj.Elts) != 1 || (obj.Lbrace.IsValid() && !f.printer.cfg.simplify) || (obj.Lbrace.IsValid() && hasDocComments(n)) || len(n.Attrs) > 0 { return nil } mem, ok := obj.Elts[0].(*ast.Field) if !ok || len(mem.Attrs) > 0 { return nil } if hasDocComments(mem) { // TODO: this inserts curly braces even in spaces where this // may not be desirable, such as: // a: // // foo // b: 3 return nil } return mem } func (f *formatter) decl(decl ast.Decl) { if decl == nil { return } defer f.after(decl) if !f.before(decl) { return } switch n := decl.(type) { case *ast.Field: constraint, _ := internal.ConstraintToken(n) f.label(n.Label, constraint) regular := isRegularField(n.Token) if regular { f.print(noblank, nooverride, n.TokenPos, token.COLON) } else { f.print(blank, nooverride, n.Token) } f.visitComments(f.current.pos) if mem := f.inlineField(n); mem != nil { switch { default: fallthrough case regular && f.cfg.simplify: f.print(blank, nooverride) f.decl(mem) case mem.Label.Pos().IsNewline(): f.print(indent, formfeed) f.decl(mem) f.indent-- } return } nextFF := f.nextNeedsFormfeed(n.Value) tab := vtab if nextFF || f.prevLbraceOnLine { tab = blank } f.print(tab) if n.Value != nil { switch n.Value.(type) { case *ast.ListLit, *ast.StructLit: f.expr(n.Value) default: f.print(indent) f.expr(n.Value) f.markUnindentLine() } } else { f.current.pos++ f.visitComments(f.current.pos) } space := tab for _, a := range n.Attrs { if f.before(a) { f.print(space, a.At, a) } f.after(a) space = blank } if nextFF { f.print(formfeed) } case *ast.BadDecl: f.print(n.From, "*bad decl*", declcomma) case *ast.Package: f.print(n.PackagePos, "package") f.print(blank, n.Name, newsection, nooverride) case *ast.ImportDecl: f.print(n.Import, "import") if len(n.Specs) == 0 { f.print(blank, n.Lparen, token.LPAREN, n.Rparen, token.RPAREN, newline) break } switch { case len(n.Specs) == 1 && len(n.Specs[0].Comments()) == 0: if !n.Lparen.IsValid() { f.print(blank) f.walkSpecList(n.Specs) break } fallthrough default: f.print(blank, n.Lparen, token.LPAREN, newline, indent) f.walkSpecList(n.Specs) f.print(unindent, newline, n.Rparen, token.RPAREN, newline) } f.print(newsection, nooverride) case *ast.LetClause: if !decl.Pos().HasRelPos() || decl.Pos().RelPos() >= token.Newline { f.print(formfeed) } f.print(n.Let, token.LET, blank, nooverride) f.expr(n.Ident) f.print(blank, nooverride, n.Equal, token.BIND, blank) f.expr(n.Expr) f.print(declcomma) // implied case *ast.EmbedDecl: if !n.Pos().HasRelPos() || n.Pos().RelPos() >= token.Newline { f.print(formfeed) } f.expr(n.Expr) f.print(newline) case *ast.Attribute: f.print(n.At, n) case *ast.CommentGroup: f.printComment(n) f.print(newsection) case ast.Expr: f.embedding(n) } } func (f *formatter) embedding(decl ast.Expr) { switch n := decl.(type) { case *ast.Comprehension: if !n.Pos().HasRelPos() || n.Pos().RelPos() >= token.Newline { f.print(formfeed) } f.walkClauseList(n.Clauses, blank) f.print(blank, nooverride) f.expr(n.Value) case *ast.Ellipsis: f.ellipsis(n) case *ast.Alias: if !decl.Pos().HasRelPos() || decl.Pos().RelPos() >= token.Newline { f.print(formfeed) } f.expr(n.Ident) f.print(blank, n.Equal, token.BIND, blank) f.expr(n.Expr) f.print(declcomma) // implied // TODO: ast.CommentGroup: allows comment groups in ListLits. case ast.Expr: f.exprRaw(n, token.LowestPrec, 1) } } func (f *formatter) nextNeedsFormfeed(n ast.Expr) bool { switch x := n.(type) { case *ast.StructLit: return true case *ast.BasicLit: return strings.IndexByte(x.Value, '\n') >= 0 case *ast.ListLit: return true case *ast.ParenExpr: return f.nextNeedsFormfeed(x.X) case *ast.UnaryExpr: return f.nextNeedsFormfeed(x.X) case *ast.BinaryExpr: return f.nextNeedsFormfeed(x.X) || f.nextNeedsFormfeed(x.Y) case *ast.IndexExpr: return f.nextNeedsFormfeed(x.X) case *ast.SelectorExpr: return f.nextNeedsFormfeed(x.X) case *ast.CallExpr: for _, arg := range x.Args { if f.nextNeedsFormfeed(arg) { return true } } } return false } func (f *formatter) importSpec(x *ast.ImportSpec) { if x.Name != nil { f.label(x.Name, token.ILLEGAL) f.print(blank) } else { f.current.pos++ f.visitComments(f.current.pos) } f.expr(x.Path) f.print(newline) } func (f *formatter) label(l ast.Label, constraint token.Token) { f.before(l) defer f.after(l) switch n := l.(type) { case *ast.Alias: f.expr(n) case *ast.Ident: // Escape an identifier that has invalid characters. This may happen, // if the AST is not generated by the parser. name := n.Name if !ast.IsValidIdent(name) { name = literal.Label.Quote(n.Name) } f.print(n.NamePos, name) case *ast.BasicLit: str := n.Value // Allow any CUE string in the AST, but ensure it is formatted // according to spec. if strings.HasPrefix(str, `"""`) || strings.HasPrefix(str, "#") { if u, err := literal.Unquote(str); err == nil { str = literal.Label.Quote(u) } } f.print(n.ValuePos, str) case *ast.ListLit: f.expr(n) case *ast.ParenExpr: f.expr(n) case *ast.Interpolation: f.expr(n) default: panic(fmt.Sprintf("unknown label type %T", n)) } if constraint != token.ILLEGAL { f.print(constraint) } } func (f *formatter) ellipsis(x *ast.Ellipsis) { f.print(x.Ellipsis, token.ELLIPSIS) if x.Type != nil && !isTop(x.Type) { f.expr(x.Type) } } func (f *formatter) expr(x ast.Expr) { const depth = 1 f.expr1(x, token.LowestPrec, depth) } func (f *formatter) expr0(x ast.Expr, depth int) { f.expr1(x, token.LowestPrec, depth) } func (f *formatter) expr1(expr ast.Expr, prec1, depth int) { if f.before(expr) { f.exprRaw(expr, prec1, depth) } f.after(expr) } func (f *formatter) exprRaw(expr ast.Expr, prec1, depth int) { switch x := expr.(type) { case *ast.BadExpr: f.print(x.From, "_|_") case *ast.BottomLit: f.print(x.Bottom, token.BOTTOM) case *ast.Alias: // Aliases in expression positions are printed in short form. f.label(x.Ident, token.ILLEGAL) f.print(x.Equal, token.BIND) f.expr(x.Expr) case *ast.Ident: f.print(x.NamePos, x) case *ast.BinaryExpr: if depth < 1 { f.internalError("depth < 1:", depth) depth = 1 } f.binaryExpr(x, prec1, cutoff(x, depth), depth) case *ast.UnaryExpr: const prec = token.UnaryPrec if prec < prec1 { // parenthesis needed f.print(token.LPAREN, nooverride) f.expr(x) f.print(token.RPAREN) } else { // no parenthesis needed f.print(x.OpPos, x.Op, nooverride) f.expr1(x.X, prec, depth) } case *ast.BasicLit: f.print(x.ValuePos, x) case *ast.Interpolation: f.before(nil) for _, x := range x.Elts { f.expr0(x, depth+1) } f.after(nil) case *ast.ParenExpr: if _, hasParens := x.X.(*ast.ParenExpr); hasParens { // don't print parentheses around an already parenthesized expression // TODO: consider making this more general and incorporate precedence levels f.expr0(x.X, depth) } else { f.print(x.Lparen, token.LPAREN) f.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth f.print(x.Rparen, token.RPAREN) } case *ast.SelectorExpr: f.selectorExpr(x, depth) case *ast.IndexExpr: f.expr1(x.X, token.HighestPrec, 1) f.print(x.Lbrack, token.LBRACK) f.expr0(x.Index, depth+1) f.print(x.Rbrack, token.RBRACK) case *ast.SliceExpr: f.expr1(x.X, token.HighestPrec, 1) f.print(x.Lbrack, token.LBRACK) indices := []ast.Expr{x.Low, x.High} for i, y := range indices { if i > 0 { // blanks around ":" if both sides exist and either side is a binary expression x := indices[i-1] if depth <= 1 && x != nil && y != nil && (isBinary(x) || isBinary(y)) { f.print(blank, token.COLON, blank) } else { f.print(token.COLON) } } if y != nil { f.expr0(y, depth+1) } } f.print(x.Rbrack, token.RBRACK) case *ast.CallExpr: if len(x.Args) > 1 { depth++ } wasIndented := f.possibleSelectorExpr(x.Fun, token.HighestPrec, depth) f.print(x.Lparen, token.LPAREN) f.walkArgsList(x.Args, depth) f.print(trailcomma, noblank, x.Rparen, token.RPAREN) if wasIndented { f.print(unindent) } case *ast.StructLit: var l line ws := noblank ff := f.formfeed() switch { case len(x.Elts) == 0: // collapse curly braces if the body is empty. ffAlt := blank | nooverride for _, c := range x.Comments() { if c.Position == 1 { ffAlt = ff break } } ff = ffAlt case !x.Rbrace.HasRelPos() || !x.Elts[0].Pos().HasRelPos(): ws |= newline | nooverride } f.print(x.Lbrace, token.LBRACE, &l, ws, ff, indent) f.prevLbraceOnLine = l == f.lineout f.walkDeclList(x.Elts) f.matchUnindent() ws = noblank if f.lineout != l { ws |= newline if f.lastTok != token.RBRACE && f.lastTok != token.RBRACK { ws |= nooverride } } f.print(ws, x.Rbrace, token.RBRACE) case *ast.ListLit: ws := noblank | indent if len(x.Elts) == 0 { // collapse square brackets if the body is empty. collapseWs := blank | nooverride for _, c := range x.Comments() { if c.Position == 1 { collapseWs = ws break } } ws |= collapseWs } f.print(x.Lbrack, token.LBRACK, ws) f.walkListElems(x.Elts) f.print(trailcomma, noblank) f.visitComments(f.current.pos) f.matchUnindent() f.print(noblank, x.Rbrack, token.RBRACK) case *ast.Ellipsis: f.ellipsis(x) default: panic(fmt.Sprintf("unimplemented type %T", x)) } } func (f *formatter) clause(clause ast.Clause) { switch n := clause.(type) { case *ast.ForClause: f.print(n.For, "for", blank) f.print(indent) if n.Key != nil { f.label(n.Key, token.ILLEGAL) f.print(n.Colon, token.COMMA, blank) } else { f.current.pos++ f.visitComments(f.current.pos) } f.label(n.Value, token.ILLEGAL) f.print(blank, n.In, "in", blank) f.expr(n.Source) f.markUnindentLine() case *ast.IfClause: f.print(n.If, "if", blank) f.print(indent) f.expr(n.Condition) f.markUnindentLine() case *ast.LetClause: // TODO(mvdan): LetClause is handled in both the clause and decl methods, // because at the semantic level it is different in each case, but the code is repetitive. f.print(n.Let, token.LET, blank, nooverride) f.print(indent) f.expr(n.Ident) f.print(blank, nooverride, n.Equal, token.BIND, blank) f.expr(n.Expr) f.markUnindentLine() default: panic("unknown clause type") } } func walkBinary(e *ast.BinaryExpr) (has6, has7, has8 bool, maxProblem int) { switch e.Op.Precedence() { case 6: has6 = true case 7: has7 = true case 8: has8 = true } switch l := e.X.(type) { case *ast.BinaryExpr: if l.Op.Precedence() < e.Op.Precedence() { // parens will be inserted. // pretend this is an *ast.ParenExpr and do nothing. break } h6, h7, h8, mp := walkBinary(l) has6 = has6 || h6 has7 = has7 || h7 has8 = has8 || h8 if maxProblem < mp { maxProblem = mp } } switch r := e.Y.(type) { case *ast.BinaryExpr: if r.Op.Precedence() <= e.Op.Precedence() { // parens will be inserted. // pretend this is an *ast.ParenExpr and do nothing. break } h6, h7, h8, mp := walkBinary(r) has6 = has6 || h6 has7 = has7 || h7 has8 = has8 || h8 if maxProblem < mp { maxProblem = mp } case *ast.UnaryExpr: switch e.Op.String() + r.Op.String() { case "/*": maxProblem = 8 case "++", "--": if maxProblem < 6 { maxProblem = 6 } } } return } func cutoff(e *ast.BinaryExpr, depth int) int { has6, has7, has8, maxProblem := walkBinary(e) if maxProblem > 0 { return maxProblem + 1 } if (has6 || has7) && has8 { if depth == 1 { return 8 } if has7 { return 7 } return 6 } if has6 && has7 { if depth == 1 { return 7 } return 6 } if depth == 1 { return 8 } return 6 } func diffPrec(expr ast.Expr, prec int) int { x, ok := expr.(*ast.BinaryExpr) if !ok || prec != x.Op.Precedence() { return 1 } return 0 } func reduceDepth(depth int) int { depth-- if depth < 1 { depth = 1 } return depth } // Format the binary expression: decide the cutoff and then format. // Let's call depth == 1 Normal mode, and depth > 1 Compact mode. // (Algorithm suggestion by Russ Cox.) // // The precedences are: // // 7 * / % quo rem div mod // 6 + - // 5 == != < <= > >= // 4 && // 3 || // 2 & // 1 | // // The only decision is whether there will be spaces around levels 6 and 7. // There are never spaces at level 8 (unary), and always spaces at levels 5 and below. // // To choose the cutoff, look at the whole expression but excluding primary // expressions (function calls, parenthesized exprs), and apply these rules: // // 1. If there is a binary operator with a right side unary operand // that would clash without a space, the cutoff must be (in order): // // /* 8 // ++ 7 // not necessary, but to avoid confusion // -- 7 // // (Comparison operators always have spaces around them.) // // 2. If there is a mix of level 7 and level 6 operators, then the cutoff // is 7 (use spaces to distinguish precedence) in Normal mode // and 6 (never use spaces) in Compact mode. // // 3. If there are no level 6 operators or no level 7 operators, then the // cutoff is 8 (always use spaces) in Normal mode // and 6 (never use spaces) in Compact mode. func (f *formatter) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) { f.nestExpr++ defer func() { f.nestExpr-- }() prec := x.Op.Precedence() if prec < prec1 { // parenthesis needed // Note: The parser inserts a ast.ParenExpr node; thus this case // can only occur if the AST is created in a different way. // defer p.pushComment(nil).pop() f.print(token.LPAREN, nooverride) f.expr0(x, reduceDepth(depth)) // parentheses undo one level of depth f.print(token.RPAREN) return } printBlank := prec < cutoff f.expr1(x.X, prec, depth+diffPrec(x.X, prec)) f.print(nooverride) if printBlank { f.print(blank) } f.print(x.OpPos, x.Op) if x.Y.Pos().IsNewline() { // at least one line break, but respect an extra empty line // in the source f.print(formfeed) printBlank = false // no blank after line break } else { f.print(nooverride) } if printBlank { f.print(blank) } f.expr1(x.Y, prec+1, depth+1) } func isBinary(expr ast.Expr) bool { _, ok := expr.(*ast.BinaryExpr) return ok } func (f *formatter) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool { if x, ok := expr.(*ast.SelectorExpr); ok { return f.selectorExpr(x, depth) } f.expr1(expr, prec1, depth) return false } // selectorExpr handles an [*ast.SelectorExpr] node and returns whether x spans // multiple lines. func (f *formatter) selectorExpr(x *ast.SelectorExpr, depth int) bool { f.expr1(x.X, token.HighestPrec, depth) f.print(token.PERIOD) if x.Sel.Pos().IsNewline() { f.print(indent, formfeed) f.expr(x.Sel.(ast.Expr)) f.print(unindent) return true } f.print(noblank) f.expr(x.Sel.(ast.Expr)) return false } func isTop(e ast.Expr) bool { ident, ok := e.(*ast.Ident) return ok && ident.Name == "_" } cue-lang-cue-db9cc73/cue/format/node_test.go000066400000000000000000000046711474664451600210670ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package format import ( "strings" "testing" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/token" "cuelang.org/go/internal" ) // TestInvalidAST verifies behavior for various invalid AST inputs. In some // cases it is okay to be permissive, as long as the output is correct. func TestInvalidAST(t *testing.T) { ident := func(s string) *ast.Ident { return &ast.Ident{NamePos: token.NoSpace.Pos(), Name: s} } testCases := []struct { desc string node ast.Node out string }{{ desc: "label sequence for definition", node: &ast.Field{Label: ident("foo"), Value: ast.NewStruct( ident("#bar"), token.COLON, &ast.StructLit{}, )}, // Force a new struct. out: `foo: { #bar: {} }`, }, { desc: "label with invalid identifier", node: &ast.Field{Label: &ast.Ident{}, Value: ast.NewString("foo")}, // Force a new struct. out: `"": "foo"`, }, { desc: "ImportDecl without parens, but imports with comments", node: func() ast.Node { n := ast.NewImport(nil, "time") ast.AddComment(n, internal.NewComment(true, "hello")) return &ast.ImportDecl{Specs: []*ast.ImportSpec{n}} }(), out: `import ( // hello "time" )`, }} for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { b, err := Node(tc.node) if err != nil { t.Fatal(err) } got := string(b) want := tc.out if got != want { t.Errorf("\ngot %v;\nwant %v", got, want) } }) } } func TestErrors(t *testing.T) { testCases := []struct { desc string node ast.Node err string }{{ desc: "empty identifier", node: ast.NewIdent(""), err: "invalid identifier", }} for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { b, err := Node(tc.node) if err == nil { t.Fatalf("expected error, found %q", b) } got := err.Error() if !strings.Contains(got, tc.err) { t.Errorf("\ngot %v;\nwant %v", got, tc.err) } }) } } cue-lang-cue-db9cc73/cue/format/printer.go000066400000000000000000000261051474664451600205620ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package format import ( "fmt" "os" "strings" "text/tabwriter" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/token" ) // A printer takes the stream of formatting tokens and spacing directives // produced by the formatter and adjusts the spacing based on the original // source code. type printer struct { cfg *config allowed whiteSpace requested whiteSpace indentStack []whiteSpace pos token.Position // current pos in AST lineout line lastTok token.Token // last token printed ([token.ILLEGAL] if it's whitespace) output []byte indent int spaceBefore bool prevLbraceOnLine bool // true if a '{' has been written on the current line // TODO(mvdan): This is similar to nooverride but used only for comments, // to ensure that we always print a newline after them. // We should fix our logic with whiteSpace instead, but for now this ensures // we don't break the syntax by omitting the newline after a comment. printingComment bool errs errors.Error } type line int func (p *printer) init(cfg *config) { p.cfg = cfg p.pos = token.Position{Line: 1, Column: 1} } func (p *printer) errf(n ast.Node, format string, args ...interface{}) { p.errs = errors.Append(p.errs, errors.Newf(n.Pos(), format, args...)) } const debug = false func (p *printer) internalError(msg ...interface{}) { if debug { fmt.Print(p.pos.String() + ": ") fmt.Println(msg...) panic("go/printer") } } func (p *printer) lineFor(pos token.Pos) int { return pos.Line() } func (p *printer) Print(v interface{}) { var ( impliedComma = false isLit bool data string nextWS whiteSpace ) switch x := v.(type) { case *line: *x = p.lineout case token.Token: s := x.String() before, after := mayCombine(p.lastTok, x) if before && !p.spaceBefore { // the previous and the current token must be // separated by a blank otherwise they combine // into a different incorrect token sequence // (except for token.INT followed by a '.' this // should never happen because it is taken care // of via binary expression formatting) if p.allowed&blank != 0 { p.internalError("whitespace buffer not empty") } p.allowed |= blank } if after { nextWS = blank } data = s switch x { case token.EOF: data = "" p.allowed = newline p.allowed &^= newsection case token.LPAREN, token.LBRACK, token.LBRACE: case token.RPAREN, token.RBRACK, token.RBRACE: impliedComma = true } p.lastTok = x case *ast.BasicLit: data = x.Value switch x.Kind { case token.STRING: // TODO: only do this when simplifying. Right now this does not // give the right result, but it should be better if: // 1) simplification is done as a separate step // 2) simplified structs are explicitly referenced separately // in the AST. if p.indent < 6 { data = literal.IndentTabs(data, p.cfg.Indent+p.indent+1) } case token.INT: if len(data) > 1 && data[0] == '0' && data[1] >= '0' && data[1] <= '9' { data = "0o" + data[1:] } // Pad trailing dot before multiplier. if p := strings.IndexByte(data, '.'); p >= 0 && data[p+1] > '9' { data = data[:p+1] + "0" + data[p+1:] } // Lowercase E, but only if it is not the last character: in the // future we may use E for Exa. if p := strings.IndexByte(data, 'E'); p != -1 && p < len(data)-1 { data = strings.ToLower(data) } case token.FLOAT: // Pad leading or trailing dots. switch p := strings.IndexByte(data, '.'); { case p < 0: case p == 0: data = "0" + data case p == len(data)-1: data += "0" case data[p+1] > '9': data = data[:p+1] + "0" + data[p+1:] } if strings.IndexByte(data, 'E') != -1 { data = strings.ToLower(data) } } isLit = true impliedComma = true p.lastTok = x.Kind case *ast.Ident: data = x.Name if !ast.IsValidIdent(data) { p.errf(x, "invalid identifier %q", x.Name) data = "*bad identifier*" } impliedComma = true p.lastTok = token.IDENT case string: // We can print a Go string as part of a CUE identifier or literal; // for example, see the formatter.label method. isLit = true data = x impliedComma = true p.lastTok = token.STRING case *ast.CommentGroup: rel := x.Pos().RelPos() if x.Line { // TODO: we probably don't need this. rel = token.Blank } switch rel { case token.NoRelPos: case token.Newline, token.NewSection: case token.Blank, token.Elided: p.allowed |= blank fallthrough case token.NoSpace: p.allowed &^= newline | newsection | formfeed | declcomma } return case *ast.Attribute: isLit = true data = x.Text impliedComma = true p.lastTok = token.ATTRIBUTE case *ast.Comment: // TODO: if implied comma, postpone comment isLit = true data = x.Text p.lastTok = token.COMMENT case whiteSpace: p.allowed |= x return case token.Pos: // TODO: should we use a known file position to synchronize? Go does, // but we don't really have to. // pos := x if x.HasRelPos() { if p.allowed&nooverride == 0 { requested := p.allowed switch x.RelPos() { case token.NoSpace: requested &^= newline | newsection | formfeed case token.Blank: requested |= blank requested &^= newline | newsection | formfeed case token.Newline: requested |= newline case token.NewSection: requested |= newsection } if p.printingComment { requested |= newline } p.writeWhitespace(requested) p.allowed = 0 p.requested = 0 } // p.pos = pos } return default: fmt.Fprintf(os.Stderr, "print: unsupported argument %v (%T)\n", x, x) panic("go/printer type") } p.writeWhitespace(p.allowed) p.allowed = 0 p.requested = 0 p.printingComment = false p.writeString(data, isLit) p.allowed = nextWS _ = impliedComma // TODO: delay comment printings } func (p *printer) writeWhitespace(ws whiteSpace) { if ws&comma != 0 { switch { case ws&(newsection|newline|formfeed) != 0, ws&trailcomma == 0: p.writeByte(',', 1) } } if ws&indent != 0 { p.markLineIndent(ws) } if ws&unindent != 0 { p.markUnindentLine() } switch { case ws&newsection != 0: p.maybeIndentLine(ws) p.writeByte('\f', 2) p.incrementLine(2) p.spaceBefore = true case ws&formfeed != 0: p.maybeIndentLine(ws) p.writeByte('\f', 1) p.incrementLine(1) p.spaceBefore = true case ws&newline != 0: p.maybeIndentLine(ws) p.writeByte('\n', 1) p.incrementLine(1) p.spaceBefore = true case ws&declcomma != 0: p.writeByte(',', 1) p.writeByte(' ', 1) p.spaceBefore = true case ws&noblank != 0: case ws&vtab != 0: p.writeByte('\v', 1) p.spaceBefore = true case ws&blank != 0: p.writeByte(' ', 1) p.spaceBefore = true } } func (p *printer) incrementLine(n int) { if n != 0 { p.prevLbraceOnLine = false } p.lineout += line(n) } func (p *printer) markLineIndent(ws whiteSpace) { p.indentStack = append(p.indentStack, ws) } func (p *printer) markUnindentLine() (wasUnindented bool) { last := len(p.indentStack) - 1 if ws := p.indentStack[last]; ws&indented != 0 { p.indent-- wasUnindented = true } p.indentStack = p.indentStack[:last] return wasUnindented } func (p *printer) maybeIndentLine(ws whiteSpace) { if ws&unindent == 0 && len(p.indentStack) > 0 { last := len(p.indentStack) - 1 if ws := p.indentStack[last]; ws&indented != 0 || ws&indent == 0 { return } p.indentStack[last] |= indented p.indent++ } } func (f *formatter) matchUnindent() whiteSpace { f.allowed |= unindent // TODO: make this work. Whitespace from closing bracket should match that // of opening if there is no position information. // f.allowed &^= nooverride | newline | newsection | formfeed | blank | noblank // ws := f.indentStack[len(f.indentStack)-1] // mask := blank | noblank | vtab // f.allowed |= unindent | blank | noblank // if ws&newline != 0 || ws*indented != 0 { // f.allowed |= newline // } return 0 } // writeString writes the string s to p.output and updates p.pos, p.out, // and p.last. If isLit is set, s is escaped w/ tabwriter.Escape characters // to protect s from being interpreted by the tabwriter. // // Note: writeString is only used to write Go tokens, literals, and // comments, all of which must be written literally. Thus, it is correct // to always set isLit = true. However, setting it explicitly only when // needed (i.e., when we don't know that s contains no tabs or line breaks) // avoids processing extra escape characters and reduces run time of the // printer benchmark by up to 10%. func (p *printer) writeString(s string, isLit bool) { if s != "" { p.spaceBefore = false } if isLit { // Protect s such that is passes through the tabwriter // unchanged. Note that valid Go programs cannot contain // tabwriter.Escape bytes since they do not appear in legal // UTF-8 sequences. p.output = append(p.output, tabwriter.Escape) } p.output = append(p.output, s...) if isLit { p.output = append(p.output, tabwriter.Escape) } // update positions nLines := 0 var li int // index of last newline; valid if nLines > 0 for i := 0; i < len(s); i++ { // CUE tokens cannot contain '\f' - no need to look for it if s[i] == '\n' { nLines++ li = i } } p.pos.Offset += len(s) if nLines > 0 { p.pos.Line += nLines c := len(s) - li p.pos.Column = c } else { p.pos.Column += len(s) } } func (p *printer) writeByte(ch byte, n int) { for i := 0; i < n; i++ { p.output = append(p.output, ch) } // update positions p.pos.Offset += n if ch == '\n' || ch == '\f' { p.pos.Line += n p.pos.Column = 1 n := p.cfg.Indent + p.indent // include base indentation for i := 0; i < n; i++ { p.output = append(p.output, '\t') } // update positions p.pos.Offset += n p.pos.Column += n return } p.pos.Column += n } // TODO(mvdan): mayCombine as a name was carried over from Go, // but it doesn't really make sense as a name for our logic here, // since we return true when either side must use a blank space. func mayCombine(prev, next token.Token) (before, after bool) { s := next.String() if 'a' <= s[0] && s[0] < 'z' { if prev == token.ILLEGAL { // If we're printing the first token, // we don't need a blank space before it. return false, true } return true, true } switch prev { case token.IQUO, token.IREM, token.IDIV, token.IMOD: return false, false case token.INT: before = next == token.PERIOD // 1. case token.ADD: before = s[0] == '+' // ++ case token.SUB: before = s[0] == '-' // -- case token.QUO: before = s[0] == '*' // /* } return before, false } cue-lang-cue-db9cc73/cue/format/simplify.go000066400000000000000000000053211474664451600207300ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package format import ( "strconv" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/internal" ) // labelSimplifier rewrites string labels to identifiers if // no identifiers will subsequently bind to the exposed label. // In other words, string labels are only replaced if this does // not change the semantics of the CUE code. type labelSimplifier struct { parent *labelSimplifier scope map[string]bool } func (s *labelSimplifier) processDecls(decls []ast.Decl) { sc := labelSimplifier{parent: s, scope: map[string]bool{}} for _, d := range decls { switch x := d.(type) { case *ast.Field: ast.Walk(x.Label, sc.markStrings, nil) } } for _, d := range decls { switch x := d.(type) { case *ast.Field: ast.Walk(x.Value, sc.markReferences, nil) default: ast.Walk(x, sc.markReferences, nil) } } for _, d := range decls { switch x := d.(type) { case *ast.Field: if _, ok := x.Label.(*ast.BasicLit); ok { x.Label = astutil.Apply(x.Label, nil, sc.replace).(ast.Label) } } } } func (s *labelSimplifier) markReferences(n ast.Node) bool { // Record strings at this level. switch x := n.(type) { case *ast.File: s.processDecls(x.Decls) return false case *ast.StructLit: s.processDecls(x.Elts) return false case *ast.SelectorExpr: ast.Walk(x.X, s.markReferences, nil) return false case *ast.Ident: for c := s; c != nil; c = c.parent { if _, ok := c.scope[x.Name]; ok { c.scope[x.Name] = false break } } } return true } func (s *labelSimplifier) markStrings(n ast.Node) bool { switch x := n.(type) { case *ast.BasicLit: str, err := strconv.Unquote(x.Value) if err != nil || !ast.IsValidIdent(str) || internal.IsDefOrHidden(str) { return false } s.scope[str] = true case *ast.Ident: s.scope[x.Name] = true case *ast.ListLit, *ast.Interpolation: return false } return true } func (s *labelSimplifier) replace(c astutil.Cursor) bool { switch x := c.Node().(type) { case *ast.BasicLit: str, err := strconv.Unquote(x.Value) if err == nil && s.scope[str] && !internal.IsDefOrHidden(str) { c.Replace(ast.NewIdent(str)) } } return false } cue-lang-cue-db9cc73/cue/format/testdata/000077500000000000000000000000001474664451600203555ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/format/testdata/comments.txtar000066400000000000000000000074631474664451600233000ustar00rootroot00000000000000simplify -- comments.input -- // Package line 1 group 1 // Package line 2 group 1 // Package line 1 - group 2 // Package line 2 - group 2 package comments // Emit line 1 group 1 // Emit line 1 group 2 // Emit line 2 group 2 { // Inside Emit } a: 3 // a line comment b: 4 // line comment that is last in the file. cc: 555 // align comments // don't simplify a: { b: 2 } // simplify a: { b: c: { d: 1 } } // unchanged a: b: [1] // don't simplify a: b: { c: 2 } // rewrite okay a: b: c: { d: 2 } m: { } m: { // empty with comment } // Issue #478 struct1: { // This is a comment // This is a comment // Another comment something: { } // extra comment } struct2: { // This is a comment // This is a comment // Another comment something: { } // extra comment } list1: [ // Comment1 // Comment2 // Another comment { }, // Comment 3 ] list2: [ // foo ] list3: [ // foo // bar ] list4: [ 1, // number a.b, // selector (a), // paren +1, // unary a[0], // index a[2:3], // slice strings.Sort([1, 2]), // call a.b, // under selector a.b, // multiple // under // selector ] funcArg1: foo( // Comment1 // Comment2 3 // Comment3 ) funcArg2: foo( // Comment1 // Comment2 3 // Comment3 ) funcArg3: foo( 2, // Comment1 // Comment2 3 // Comment3 ) // comment including some tabs // issue #2567 foo: [ bar["baz"], //some comment ] [ if true // inline comment {}] { // comments ... // surrounding // an ellipsis foo: { // some [string]: _ // comment } } -- comments.golden -- // Package line 1 group 1 // Package line 2 group 1 // Package line 1 - group 2 // Package line 2 - group 2 package comments // Emit line 1 group 1 // Emit line 1 group 2 // Emit line 2 group 2 { // Inside Emit } a: 3 // a line comment b: 4 // line comment that is last in the file. cc: 555 // align comments // don't simplify a: { b: 2 } // simplify a: { b: c: d: 1 } // unchanged a: b: [1] // don't simplify a: b: c: 2 // rewrite okay a: b: c: d: 2 m: {} m: { // empty with comment } // Issue #478 struct1: { // This is a comment // This is a comment // Another comment something: {} // extra comment } struct2: { // This is a comment // This is a comment // Another comment something: {} // extra comment } list1: [ // Comment1 // Comment2 // Another comment {}, // Comment 3 ] list2: [ // foo ] list3: [ // foo // bar ] list4: [ 1, // number a.b, // selector (a), // paren +1, // unary a[0], // index a[2:3], // slice strings.Sort([1, 2]), // call a.b, // under selector a.b, // multiple // under // selector ] funcArg1: foo( // Comment1 // Comment2 3, // Comment3 ) funcArg2: foo( // Comment1 // Comment2 3, // Comment3 ) funcArg3: foo( 2, // Comment1 // Comment2 3, // Comment3 ) // comment including some tabs // issue #2567 foo: [ bar["baz"], //some comment ] [ if true {}, // inline comment ] { foo: { // some ... // comment } // comments ... // surrounding // an ellipsis } -- comment_alone.input -- // Just one comment on its own. -- comment_alone.golden -- // Just one comment on its own. -- comment_field.input -- // Just one comment on a field. foo: string -- comment_field.golden -- // Just one comment on a field. foo: string -- comments_alone.input -- // Just a few comments // on their own. -- comments_alone.golden -- // Just a few comments // on their own. -- comments_field.input -- // Just a few comments // on a field. foo: string -- comments_field.golden -- // Just a few comments // on a field. foo: string cue-lang-cue-db9cc73/cue/format/testdata/expressions.txtar000066400000000000000000000167101474664451600240300ustar00rootroot00000000000000 -- expressions.input -- package expressions import "list" { a: 1 // comment aaa: 22 // comment "": 3 b: 3 c: b: a: 4 c?: bb?: aaa?: 5 c: b: [Name=string]: a: int let alias = 3.14 "g\("en")"?: 4 let alias2 = foo // with comment let aaalias = foo b: bar bottom: _|_ a: b: c: 2 req!: int a: bbbb: c: 3 a: b: 3 a: bb: cc: 3 empty: {} emptyNewLine: { } someObject: { a: 8 aa: 9 aaa: 10 } #someDefinition: { embedding field: 2 } #openDef: { a: int ... } attrs: { a: 8 @go(A) // comment aa: 8 @go(A) // comment bb: 9 bbb: 10 @go(Bbb) @xml(,attr) // comment bbbb: 100 @go(Bbbb) @xml(,attr) // comment } foo: bar: string @go(-) e: 1+2*3 e: 1*2*3 // error e: >=2 & <=3 e: >2 & <=(3 + 4) ex: >2 & <=(3 + 4*5) e: >2 & <=3 & <=4 e: 1 + 2 + 3 // error e: s[1+2] e: s[1:2] e: s[1+2:2+4] e: s[2] e: s[2*3] e: s[1+2*3] e: a | b| c e: a| b| c | d e: f(3+4+5) e: f(3*4*5) e: f(3+4*5) e: f(3 + 4 div 5) e: 3<4&&5>4 e: a || b && c || d e: a + +b * 3 e: -a - -b e: b + c e: b*c + d e: a*b + c e: a - b - c e: a - (b - c) e: a - b*c e: a - (b * c) e: a * b / c e: a div b + 5 e: a / b e: x[a|b] e: x[a /b] e: a & b e: a + +b e: a - -b e: a div - b e: x[a*-b] e: x[a + +b] e: len(longVariableName) * 2 e: "\(a)" e: 'aa \(aaa) aa' e: "aa \(aaa)" e: [ ] e: [ ] e: [1, 2 ] e: [1, 2] e: [1, 2, 3, 4, 5, 6, 7, 8] e: [1, 2, 3, 4, 5, 6, 7, 8 // maybe force additional comma ] e: [...] e: [ ...] e: [... ] e: [1, 2, ...] e: [1, 2, ...] e: [...int] e: [...int,] e: [...int | float] e: [for x in someObject if x > 9 { x }] e: [for x in someObject if x > 9 {x}] e: [ for x in someObject if x > 9 {x}] e: [ for x in someObject if x > 9 {x}] e: [ if x > 1 {}, if x > 1 {}, for x in src {}, ] for k, v in someObject { "\(k)": v } for k, v in someObject { "\(k)": v } e: { for k, v in someObject if k > "a" { "\(k)":v } } e: { for k, v in someObject if k > "a" {"\(k)":v} } e: { for k, v in someObject if k > "a" { "\(k)":v }} e: { for k, v in someObject let x = v if k > "a" { "\(k)":x}} if a | b { c: d } e: [{ a: 1, b: 2, }] e: [{ a: 1, b: 2, }, ] e: [{ a: 1, b: 2, }, { c: 1, d: 2, }] e: [{ a: 1, b: 2, }, 3, 4, ] e: e.f(1, 2) e: ((3 + 4)) // field before list f: 3 a: [1, 2 // add comma ] foo : bar a: "foo-bar": 3 b: a."foo-bar" c: a. "foo-bar" . b d: a. "foo-bar" e: a. "foo-bar". b f: 2 "contains tabs": 123 @jsonschema(foo="contains tabs") j: cueckoo: _ | [ 1, 2, ] k: cueckoo: *[ 1, 2, ] l: cueckoo: list.Concat([ 1, 2, ]) m: [1, 2, 3] m: [1, 2, 3,] m: [ 1, 2, 3, ] m: [ 1, 2, 3,] m: [ 1, 2, 3,] m: [ 1, 2, 3] m: [ 1, 2, 3,] m: [ 1, 2, 3, ] m: [ 1, 2, 3 ] m: [ if true { 1 }, 2, 3] n: [ 1] o: [{}] o: [ {}] o: [{} ] o: [ {} ] p: 1 p: p & {p: 2} q: 1 q: q | {q: 2} r: 1 r: b & [1, 2, {a: 4}] s: [string]: [string]: a s: [string]: {s: string} } -- expressions.golden -- package expressions import "list" { a: 1 // comment aaa: 22 // comment "": 3 b: 3 c: b: a: 4 c?: bb?: aaa?: 5 c: b: [Name=string]: a: int let alias = 3.14 "g\("en")"?: 4 let alias2 = foo // with comment let aaalias = foo b: bar bottom: _|_ a: b: c: 2 req!: int a: bbbb: c: 3 a: b: 3 a: bb: cc: 3 empty: {} emptyNewLine: {} someObject: { a: 8 aa: 9 aaa: 10 } #someDefinition: { embedding field: 2 } #openDef: { a: int ... } attrs: { a: 8 @go(A) // comment aa: 8 @go(A) // comment bb: 9 bbb: 10 @go(Bbb) @xml(,attr) // comment bbbb: 100 @go(Bbbb) @xml(,attr) // comment } foo: { bar: string @go(-) } e: 1 + 2*3 e: 1 * 2 * 3 // error e: >=2 & <=3 e: >2 & <=(3 + 4) ex: >2 & <=(3 + 4*5) e: >2 & <=3 & <=4 e: 1 + 2 + 3 // error e: s[1+2] e: s[1:2] e: s[1+2 : 2+4] e: s[2] e: s[2*3] e: s[1+2*3] e: a | b | c e: a | b | c | d e: f(3 + 4 + 5) e: f(3 * 4 * 5) e: f(3 + 4*5) e: f(3 + 4 div 5) e: 3 < 4 && 5 > 4 e: a || b && c || d e: a + +b*3 e: -a - -b e: b + c e: b*c + d e: a*b + c e: a - b - c e: a - (b - c) e: a - b*c e: a - (b * c) e: a * b / c e: a div b + 5 e: a / b e: x[a | b] e: x[a/b] e: a & b e: a + +b e: a - -b e: a div -b e: x[a*-b] e: x[a + +b] e: len(longVariableName) * 2 e: "\(a)" e: 'aa \(aaa) aa' e: "aa \(aaa)" e: [] e: [] e: [1, 2, ] e: [1, 2] e: [1, 2, 3, 4, 5, 6, 7, 8] e: [1, 2, 3, 4, 5, 6, 7, 8, // maybe force additional comma ] e: [...] e: [ ...] e: [..., ] e: [1, 2, ...] e: [1, 2, ...] e: [...int] e: [...int] e: [...int | float] e: [for x in someObject if x > 9 { x }] e: [for x in someObject if x > 9 {x}] e: [ for x in someObject if x > 9 {x}] e: [ for x in someObject if x > 9 {x}] e: [ if x > 1 {}, if x > 1 {}, for x in src {}, ] for k, v in someObject { "\(k)": v } for k, v in someObject { "\(k)": v } e: { for k, v in someObject if k > "a" { "\(k)": v } } e: {for k, v in someObject if k > "a" {"\(k)": v}} e: {for k, v in someObject if k > "a" { "\(k)": v }} e: { for k, v in someObject let x = v if k > "a" { "\(k)": x }} if a | b { c: d } e: [{ a: 1, b: 2 }] e: [{ a: 1, b: 2 }, ] e: [{ a: 1, b: 2 }, { c: 1, d: 2 }] e: [{ a: 1, b: 2 }, 3, 4, ] e: e.f(1, 2) e: (3 + 4) // field before list f: 3 a: [1, 2, // add comma ] foo: bar a: "foo-bar": 3 b: a."foo-bar" c: a."foo-bar".b d: a. "foo-bar" e: a. "foo-bar". b f: 2 "contains tabs": 123 @jsonschema(foo="contains tabs") j: cueckoo: _ | [ 1, 2, ] k: cueckoo: *[ 1, 2, ] l: cueckoo: list.Concat([ 1, 2, ]) m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [1, 2, 3] m: [if true {1}, 2, 3] n: [1] o: [{}] o: [{}] o: [{}] o: [{}] p: 1 p: p & {p: 2} q: 1 q: q | {q: 2} r: 1 r: b & [1, 2, {a: 4}] s: [string]: [string]: a s: [string]: {s: string} } -- issue2496.input -- machine_type: [ if arch == "amd" {"n2-standard-2"}, if arch == "arm" {"t2a-standard-2"}, "unknown arch", ][0] long_field_name: ([ "foo" ]) long_field_name: [ "foo" ].bar // TODO(mvdan): we insert an empty line between the definitions. _foo: { #tool: string #arch: string // skip_create_image: true } -- issue2496.golden -- machine_type: [ if arch == "amd" {"n2-standard-2"}, if arch == "arm" {"t2a-standard-2"}, "unknown arch", ][0] long_field_name: ([ "foo", ]) long_field_name: [ "foo", ].bar // TODO(mvdan): we insert an empty line between the definitions. _foo: { #tool: string #arch: string // skip_create_image: true } cue-lang-cue-db9cc73/cue/format/testdata/imports.txtar000066400000000000000000000013071474664451600231370ustar00rootroot00000000000000sort-imports -- imports.input -- package foo import ( "cuelang.org/go/foo" "cuelang.org/go/bar" "time" ) import ( time1 "time" // comment f2 f2 "cuelang.org/go/foo" f1 "cuelang.org/go/foo" ) import ( time2 "time" same "cuelang.org/go/foo" // comment 1 same2 "cuelang.org/go/foo" // comment 2 ) a: time.time b: foo.foo c: bar.Bar -- imports.golden -- package foo import ( "cuelang.org/go/foo" "cuelang.org/go/bar" "time" ) import ( time1 "time" // comment f2 f2 "cuelang.org/go/foo" f1 "cuelang.org/go/foo" ) import ( time2 "time" same "cuelang.org/go/foo" // comment 1 same2 "cuelang.org/go/foo" // comment 2 ) a: time.time b: foo.foo c: bar.Bar cue-lang-cue-db9cc73/cue/format/testdata/issue1544.txtar000066400000000000000000000003431474664451600231070ustar00rootroot00000000000000-- if.input -- if true { x: 5 } -- if.golden -- if true { x: 5 } -- let.input -- let x = 5 y: x -- let.golden -- let x = 5 y: x -- for.input -- for v in ["a", "b"] { (v): v } -- for.golden -- for v in ["a", "b"] { (v): v } cue-lang-cue-db9cc73/cue/format/testdata/issue3291.txtar000066400000000000000000000005431474664451600231120ustar00rootroot00000000000000-- file.input -- A: true B: [ 1, // this comment is fine 2, // this comment is fine if A { 3 // this comment ends up touching its element }, 4, // this comment is fine ] -- file.golden -- A: true B: [ 1, // this comment is fine 2, // this comment is fine if A { 3 // this comment ends up touching its element }, 4, // this comment is fine ] cue-lang-cue-db9cc73/cue/format/testdata/simplify.txtar000066400000000000000000000046331474664451600233030ustar00rootroot00000000000000simplify -- simplify.input -- import "time" "foo": "bar": "str" a: "B": 42 "a.b": "foo-": "cc_dd": x @attr(3) a: b: c: 3 // references to bar are all shadowed and this can be safely turned into // an identifier. "bar": "str" // These references would be directly referred to if turned into an identifier. // The quotes should therefore not be removed. "baz1": 3 "baz2": 3 "baz3": 3 // TODO: could be simplified. // These string labels may be turned into an identifier. "qux": 4 "quux": 5 // TODO(legacy): Don't simplify "hidden" fields for now. "_foo": 3 // Issue #294 "\("x")": "x" (x): "foo" (x)?: "foo" (x)!: "foo" a: { [string]: _ foo: 2 } "#A": dontSimplify x: { @tag0(foo) r1: baz1 bar: r2: bar r3: bar E=quux: 3 @tag1(bar) r4: quux [baz2="str"]: 4 r5: baz2 [baz3="bar"]: name: baz3 "Time": time.Time } y: { "a": { "bar": "a-value" [!="bar"]: {} } "b": { "x": { "bar": "bar" "baz": "baz" [!={ "a": "baz" }.a & !="bar"]: {} } "y": { "bar": "a-value" ({ "a": "bar" }.a): {} } } } { foo: {} bar: "foo": foo // removing the quotes would cause a cyclic reference } -- simplify.golden -- import "time" foo: bar: "str" a: B: 42 "a.b": "foo-": cc_dd: x @attr(3) a: b: c: 3 // references to bar are all shadowed and this can be safely turned into // an identifier. bar: "str" // These references would be directly referred to if turned into an identifier. // The quotes should therefore not be removed. "baz1": 3 "baz2": 3 "baz3": 3 // TODO: could be simplified. // These string labels may be turned into an identifier. qux: 4 quux: 5 // TODO(legacy): Don't simplify "hidden" fields for now. "_foo": 3 // Issue #294 "\("x")": "x" (x): "foo" (x)?: "foo" (x)!: "foo" a: { foo: 2 ... } "#A": dontSimplify x: { @tag0(foo) r1: baz1 bar: r2: bar r3: bar E=quux: 3 @tag1(bar) r4: quux [baz2="str"]: 4 r5: baz2 [baz3="bar"]: name: baz3 Time: time.Time } y: { a: { bar: "a-value" [!="bar"]: {} } b: { x: { bar: "bar" baz: "baz" [!={ "a": "baz" }.a & !="bar"]: {} } y: { bar: "a-value" ({ "a": "bar" }.a): {} } } } { foo: {} bar: "foo": foo // removing the quotes would cause a cyclic reference } cue-lang-cue-db9cc73/cue/format/testdata/values.txtar000066400000000000000000000003731474664451600227430ustar00rootroot00000000000000 -- values.input -- a: 0e+1 a: 0e1 a: 0E+1 a: 0E1 a: .3e+1 a: .3E+1 a: .3 a: 3. a: 3.T a: 3.e100 s: """ x\"\"\" """ -- values.golden -- a: 0e+1 a: 0e1 a: 0e+1 a: 0e1 a: 0.3e+1 a: 0.3e+1 a: 0.3 a: 3.0 a: 3.0T a: 3.0e100 s: """ x\"\"\" """ cue-lang-cue-db9cc73/cue/format_test.go000066400000000000000000000106201474664451600201310ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "path" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" ) func ExampleValue_Format() { ctx := cuecontext.New() v := ctx.CompileString(` a: 2 + b b: *3 | int s: "foo\nbar" `) fmt.Println("### ALL") fmt.Println(v) fmt.Println("---") fmt.Printf("%#v\n", v) fmt.Println("---") fmt.Printf("%+v\n", v) a := v.LookupPath(cue.ParsePath("a")) fmt.Println("\n### INT") fmt.Printf("%%v: %v\n", a) fmt.Printf("%%05d: %05d\n", a) s := v.LookupPath(cue.ParsePath("s")) fmt.Println("\n### STRING") fmt.Printf("%%v: %v\n", s) fmt.Printf("%%s: %s\n", s) fmt.Printf("%%q: %q\n", s) v = ctx.CompileString(` #Def: a: [string]: int b: #Def b: a: { a: 3 b: 3 } `) b := v.LookupPath(cue.ParsePath("b.a")) fmt.Println("\n### DEF") fmt.Println(b) fmt.Println("---") // This will indicate that the result is closed by including a hidden // definition. fmt.Printf("%#v\n", b) // Output: // ### ALL // { // a: 5 // b: *3 | int // s: """ // foo // bar // """ // } // --- // a: 2 + b // b: *3 | int // s: "foo\nbar" // --- // { // a: 5 // b: 3 // s: """ // foo // bar // """ // } // // ### INT // %v: 5 // %05d: 00005 // // ### STRING // %v: """ // foo // bar // """ // %s: foo // bar // %q: "foo\nbar" // // ### DEF // { // a: 3 // b: 3 // } // --- // _#def // _#def: { // { // [string]: int // } // a: 3 // b: 3 // } } func TestFormat(t *testing.T) { tests := func(s ...string) (a [][2]string) { for i := 0; i < len(s); i += 2 { a = append(a, [2]string{s[i], s[i+1]}) } return a } testCases := []struct { desc string in string out [][2]string }{{ desc: "int", in: `12 + 14`, out: tests( "%#v", "26", "%d", "26", "%o", "32", "%O", "0o32", "%x", "1a", "%X", "1A", "%q", `"26"`, "%0.3d", "026", ), }, { desc: "float", in: `12.2 + 14.4`, out: tests( "%#v", "26.6", "%5f", " 26.6", "%e", "2.66e+1", "%08E", "02.66E+1", "%g", "26.6", "%3G", "26.6", ), }, { desc: "strings", in: `"string"`, out: tests( "%v", `"string"`, "%s", "string", "%x", "737472696e67", "%X", "737472696E67", ), }, { desc: "multiline string", in: `""" foo bar """`, out: tests( "%#v", `""" foo bar """`, "%s", "foo\nbar", "%q", `"foo\nbar"`, ), }, { desc: "multiline bytes", in: `''' foo bar '''`, out: tests( "%#v", `''' foo bar '''`, "%s", "foo\nbar", "%q", `"foo\nbar"`, ), }, { desc: "interpolation", in: ` #D: { a: string b: "hello \(a)" } d: #D d: a: "world" x: *1 | int `, out: tests( "%v", `{ d: { a: "world" b: "hello world" } x: *1 | int }`, "%#v", `#D: { a: string b: "hello \(a)" } d: #D & { a: "world" } x: *1 | int`, "%+v", `{ d: { a: "world" b: "hello world" } x: 1 }`, ), }, { desc: "indent", in: ` a: { b: """ foo bar """ c: int }`, out: tests( "%v", `{ a: { b: """ foo bar """ c: int } }`, "%3v", `{ a: { b: """ foo bar """ c: int } }`, "%.1v", `{ a: { b: """ foo bar """ c: int } }`, "%3.1v", `{ a: { b: """ foo bar """ c: int } }`, ), }, { desc: "imports", in: ` import "strings" a: strings.Contains("foo") `, out: tests( "%v", `{ a: strings.Contains("foo") }`, "%+v", `{ a: strings.Contains("foo") }`, "%#v", `import "strings" a: strings.Contains("foo")`, ), }} ctx := cuecontext.New() for _, tc := range testCases { for _, test := range tc.out { t.Run(path.Join(tc.desc, test[0]), func(t *testing.T) { v := ctx.CompileString(tc.in) got := fmt.Sprintf(test[0], v) if got != test[1] { t.Errorf(" got: %s\nwant: %s", got, test[1]) } }) } } } cue-lang-cue-db9cc73/cue/instance.go000066400000000000000000000207121474664451600174110ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/compile" "cuelang.org/go/internal/core/runtime" ) // An InstanceOrValue is implemented by [Value] and [*Instance]. // // This is a placeholder type that is used to allow Instance-based APIs to // transition to Value-based APIs. The goals is to get rid of the Instance // type before v1.0.0. type InstanceOrValue interface { Value() Value internal() } func (Value) internal() {} func (*Instance) internal() {} // Value implements [InstanceOrValue]. func (v hiddenValue) Value() Value { return v } // An Instance defines a single configuration based on a collection of // underlying CUE files. // // Use of this type is being phased out in favor of [Value]. // Any APIs currently taking an Instance should use [InstanceOrValue] // to transition to the new type without breaking users. type Instance struct { index *runtime.Runtime root *adt.Vertex ImportPath string Dir string PkgName string DisplayName string Incomplete bool // true if Pkg and all its dependencies are free of errors Err errors.Error // non-nil if the package had errors inst *build.Instance } type hiddenInstance = Instance func addInst(x *runtime.Runtime, p *Instance) *Instance { if p.inst == nil { p.inst = &build.Instance{ ImportPath: p.ImportPath, PkgName: p.PkgName, } } x.AddInst(p.ImportPath, p.root, p.inst) x.SetBuildData(p.inst, p) p.index = x return p } func lookupInstance(x *runtime.Runtime, p *build.Instance) *Instance { if x, ok := x.BuildData(p); ok { return x.(*Instance) } return nil } func getImportFromBuild(x *runtime.Runtime, p *build.Instance, v *adt.Vertex) *Instance { inst := lookupInstance(x, p) if inst != nil { return inst } inst = &Instance{ ImportPath: p.ImportPath, Dir: p.Dir, PkgName: p.PkgName, DisplayName: p.ImportPath, root: v, inst: p, index: x, } if p.Err != nil { inst.setListOrError(p.Err) } x.SetBuildData(p, inst) return inst } func getImportFromNode(x *runtime.Runtime, v *adt.Vertex) *Instance { p := x.GetInstanceFromNode(v) if p == nil { return nil } return getImportFromBuild(x, p, v) } func getImportFromPath(x *runtime.Runtime, id string) *Instance { node := x.LoadImport(id) if node == nil { return nil } b := x.GetInstanceFromNode(node) inst := lookupInstance(x, b) if inst == nil { inst = &Instance{ ImportPath: b.ImportPath, PkgName: b.PkgName, root: node, inst: b, index: x, } } return inst } // newInstance creates a new instance. Use Insert to populate the instance. func newInstance(x *runtime.Runtime, p *build.Instance, v *adt.Vertex) *Instance { // TODO: associate root source with structLit. inst := &Instance{ root: v, inst: p, } if p != nil { inst.ImportPath = p.ImportPath inst.Dir = p.Dir inst.PkgName = p.PkgName inst.DisplayName = p.ImportPath if p.Err != nil { inst.setListOrError(p.Err) } } x.AddInst(p.ImportPath, v, p) x.SetBuildData(p, inst) inst.index = x return inst } func (inst *Instance) setListOrError(err errors.Error) { inst.Incomplete = true inst.Err = errors.Append(inst.Err, err) } // ID returns the package identifier that uniquely qualifies module and // package name. func (inst *Instance) ID() string { if inst == nil || inst.inst == nil { return "" } return inst.inst.ID() } // Value returns the root value of the configuration. If the configuration // defines in emit value, it will be that value. Otherwise it will be all // top-level values. func (inst *Instance) Value() Value { ctx := newContext(inst.index) inst.root.Finalize(ctx) // TODO: consider including these statistics as well. Right now, this only // seems to be used in cue cmd for "auxiliary" evaluations, like filetypes. // These arguably skew the actual statistics for the cue command line, so // it is convenient to not include these. // adt.AddStats(ctx) return newVertexRoot(inst.index, ctx, inst.root) } // Eval evaluates an expression within an existing instance. // // Expressions may refer to builtin packages if they can be uniquely identified. // // Deprecated: use // inst.Value().Context().BuildExpr(expr, Scope(inst.Value), InferBuiltins(true)) func (inst *hiddenInstance) Eval(expr ast.Expr) Value { v := inst.Value() return v.Context().BuildExpr(expr, Scope(v), InferBuiltins(true)) } // DO NOT USE. // // Deprecated: do not use. func Merge(inst ...*Instance) *Instance { v := &adt.Vertex{} i := inst[0] ctx := newContext(i.index) // TODO: interesting test: use actual unification and then on K8s corpus. for _, i := range inst { w := i.Value() v.AddConjunct(adt.MakeRootConjunct(nil, w.v.ToDataAll(ctx))) } v.Finalize(ctx) p := addInst(i.index, &Instance{ root: v, }) return p } // Build creates a new instance from the build instances, allowing unbound // identifier to bind to the top-level field in inst. The top-level fields in // inst take precedence over predeclared identifier and builtin functions. // // Deprecated: use [Context.BuildInstance] func (inst *hiddenInstance) Build(p *build.Instance) *Instance { p.Complete() idx := inst.index r := inst.index rErr := r.ResolveFiles(p) cfg := &compile.Config{Scope: valueScope(Value{idx: r, v: inst.root})} v, err := compile.Files(cfg, r, p.ID(), p.Files...) // Just like [runtime.Runtime.Build], ensure that the @embed compiler is run as needed. err = errors.Append(err, r.InjectImplementations(p, v)) v.AddConjunct(adt.MakeRootConjunct(nil, inst.root)) i := newInstance(idx, p, v) if rErr != nil { i.setListOrError(rErr) } if i.Err != nil { i.setListOrError(i.Err) } if err != nil { i.setListOrError(err) } return i } // Lookup reports the value at a path starting from the top level struct. The // Exists method of the returned value will report false if the path did not // exist. The Err method reports if any error occurred during evaluation. The // empty path returns the top-level configuration struct. Use LookupDef for definitions or LookupField for // any kind of field. // // Deprecated: use [Value.LookupPath] func (inst *hiddenInstance) Lookup(path ...string) Value { return inst.Value().Lookup(path...) } // LookupDef reports the definition with the given name within struct v. The // Exists method of the returned value will report false if the definition did // not exist. The Err method reports if any error occurred during evaluation. // // Deprecated: use [Value.LookupPath] func (inst *hiddenInstance) LookupDef(path string) Value { return inst.Value().LookupDef(path) } // LookupField reports a Field at a path starting from v, or an error if the // path is not. The empty path returns v itself. // // It cannot look up hidden or unexported fields. // // Deprecated: use [Value.LookupPath] func (inst *hiddenInstance) LookupField(path ...string) (f FieldInfo, err error) { v := inst.Value() for _, k := range path { s, err := v.Struct() if err != nil { return f, err } f, err = s.FieldByName(k, true) if err != nil { return f, err } if f.IsHidden { return f, errNotFound } v = f.Value } return f, err } // Fill creates a new instance with the values of the old instance unified with // the given value. It is not possible to update the emit value. // // Values may be any Go value that can be converted to CUE, an ast.Expr or // a Value. In the latter case, it will panic if the Value is not from the same // Runtime. // // Deprecated: use [Value.FillPath] func (inst *hiddenInstance) Fill(x interface{}, path ...string) (*Instance, error) { v := inst.Value().Fill(x, path...) inst = addInst(inst.index, &Instance{ root: v.v, inst: nil, // Omit ImportPath to indicate this is not an importable package. Dir: inst.Dir, PkgName: inst.PkgName, Incomplete: inst.Incomplete, }) return inst, nil } cue-lang-cue-db9cc73/cue/interpreter/000077500000000000000000000000001474664451600176175ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/embed/000077500000000000000000000000001474664451600206735ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/embed/embed.go000066400000000000000000000270621474664451600223050ustar00rootroot00000000000000// Copyright 2024 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package embed provides capabilities to CUE to embed any file that resides // within a CUE module into CUE either verbatim or decoded. // // This package is EXPERIMENTAL and subject to change. // // # Overview // // To enable file embedding, a file must include the file-level @extern(embed) // attribute. This allows a quick glance to see if a file embeds any files at // all. This allows the @embed attribute to be used to load a file within a CUE // module into a field. // // References to files are always relative to directory in which the referring // file resides. Only files that exist within the CUE module are accessible. // // # The @embed attribute // // There are two main ways to embed files which are distinguished by the file // and glob arguments. The @embed attribute supports the following arguments: // // file=$filename // // The use of the file argument tells embed to load a single file into the // field. This argument many not be used in conjunction with the glob argument. // // glob=$pattern // // The use of the glob argument tells embed to load multiple files into the // field as a map of file paths to the decoded values. The paths are normalized // to use forward slashes. This argument may not be used in conjunction with the // file argument. // // type=$type // // By default, the file type is interpreted based on the file extension. This // behavior can be overridden by the type argument. See cue help filetypes for // the list of supported types. This field is required if a file extension is // unknown, or if a wildcard is used for the file extension in the glob pattern. // // # Limitations // // The embed interpreter currently does not support: // - stream values, such as .ndjson or YAML streams. // - schema-based decoding, such as needed for textproto // // # Example // // @extern(embed) // // package foo // // // interpreted as JSON // a: _ @embed(file="file1.json") // the quotes are optional here // // // interpreted the same file as JSON schema // #A: _ @embed(file=file1.json, type=jsonschema) // // // interpret a proprietary extension as OpenAPI represented as YAML // b: _ @embed(file="file2.crd", type=openapi+yaml) // // // include all YAML files in the x directory interpreted as YAML // // The result is a map of file paths to the decoded YAML values. // files: _ @embed(glob=x/*.yaml) // // // include all files in the y directory as a map of file paths to binary // // data. The entries are unified into the same map as above. // files: _ @embed(glob=y/*.*, type=binary) package embed import ( "io/fs" "os" "path" "path/filepath" "strings" "cuelang.org/go/cue" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/runtime" "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" "cuelang.org/go/internal/value" pkgpath "cuelang.org/go/pkg/path" ) // TODO: obtain a fs.FS from load or something similar // TODO: disallow files from submodules // TODO: record files in build.Instance // TODO: support stream values // TODO: support schema-based decoding // TODO: maybe: option to include hidden files? // interpreter is a [cuecontext.ExternInterpreter] for embedded files. type interpreter struct{} // New returns a new interpreter for embedded files as a // [cuecontext.ExternInterpreter] suitable for passing to [cuecontext.New]. func New() cuecontext.ExternInterpreter { return &interpreter{} } func (i *interpreter) Kind() string { return "embed" } // NewCompiler returns a compiler that can decode and embed files that exist // within a CUE module. func (i *interpreter) NewCompiler(b *build.Instance, r *runtime.Runtime) (runtime.Compiler, errors.Error) { if b.Module == "" { return nil, errors.Newf(token.Pos{}, "cannot embed files when not in a module") } if b.Root == "" { return nil, errors.Newf(token.Pos{}, "cannot embed files: no module root found") } return &compiler{ b: b, runtime: (*cue.Context)(r), }, nil } // A compiler is a [runtime.Compiler] that allows embedding files into CUE // values. type compiler struct { b *build.Instance runtime *cue.Context opCtx *adt.OpContext // file system cache dir string fs fs.StatFS pos token.Pos } // Compile interprets an embed attribute to either load a file // (@embed(file=...)) or a glob of files (@embed(glob=...)). // and decodes the given files. func (c *compiler) Compile(funcName string, scope adt.Value, a *internal.Attr) (adt.Expr, errors.Error) { file, _, err := a.Lookup(0, "file") if err != nil { return nil, errors.Promote(err, "invalid attribute") } glob, _, err := a.Lookup(0, "glob") if err != nil { return nil, errors.Promote(err, "invalid attribute") } typ, _, err := a.Lookup(0, "type") if err != nil { return nil, errors.Promote(err, "invalid type argument") } c.opCtx = adt.NewContext((*runtime.Runtime)(c.runtime), nil) pos := a.Pos c.pos = pos // Jump through some hoops to get file operations to behave the same for // Windows and Unix. // TODO: obtain a fs.FS from load or something similar. dir := filepath.Dir(pos.File().Name()) if c.dir != dir { c.fs = os.DirFS(dir).(fs.StatFS) // Documented as implementing fs.StatFS c.dir = dir } switch { case file == "" && glob == "": return nil, errors.Newf(a.Pos, "attribute must have file or glob field") case file != "" && glob != "": return nil, errors.Newf(a.Pos, "attribute cannot have both file and glob field") case file != "": return c.processFile(file, typ, scope) default: // glob != "": return c.processGlob(glob, typ, scope) } } func (c *compiler) processFile(file, scope string, schema adt.Value) (adt.Expr, errors.Error) { file, err := c.clean(file) if err != nil { return nil, err } for dir := path.Dir(file); dir != "."; dir = path.Dir(dir) { if _, err := c.fs.Stat(path.Join(dir, "cue.mod")); err == nil { return nil, errors.Newf(c.pos, "cannot embed file %q: in different module", file) } } return c.decodeFile(file, scope, schema) } func (c *compiler) processGlob(glob, scope string, schema adt.Value) (adt.Expr, errors.Error) { glob, ce := c.clean(glob) if ce != nil { return nil, ce } // Validate that the glob pattern is valid per [pkgpath.Match]. // Note that we use Unix match semantics because all embed paths are Unix-like. if _, err := pkgpath.Match(glob, "", pkgpath.Unix); err != nil { return nil, errors.Wrapf(err, c.pos, "invalid glob pattern %q", glob) } // If we do not have a type, ensure the extension of the base is fully // specified, i.e. does not contain any meta characters as specified by // path.Match. if scope == "" { ext := path.Ext(path.Base(glob)) if ext == "" || strings.ContainsAny(ext, "*?[\\") { return nil, errors.Newf(c.pos, "extension not fully specified; type argument required") } } m := &adt.StructLit{} matches, err := fs.Glob(c.fs, glob) if err != nil { return nil, errors.Promote(err, "failed to match glob") } dirs := make(map[string]string) for _, f := range matches { if c.isHidden(f) { // TODO: allow option for including hidden files? continue } // TODO: lots of stat calls happening in this MVP so another won't hurt. // We don't support '**' initially, and '*' only matches files, so skip // any directories. if fi, err := c.fs.Stat(f); err != nil { return nil, errors.Newf(c.pos, "failed to stat %s: %v", f, err) } else if fi.IsDir() { continue } // Add all parents of the embedded file that // aren't the current directory (if there's a cue.mod // in the current directory, that's the current module // not nested). for dir := path.Dir(f); dir != "."; dir = path.Dir(dir) { dirs[dir] = f } expr, err := c.decodeFile(f, scope, schema) if err != nil { return nil, err } m.Decls = append(m.Decls, &adt.Field{ Label: c.opCtx.StringLabel(f), Value: expr, }) } // Check that none of the matches were in a nested module // directory. for dir, f := range dirs { if _, err := c.fs.Stat(path.Join(dir, "cue.mod")); err == nil { return nil, errors.Newf(c.pos, "cannot embed file %q: in different module", f) } } return m, nil } func (c *compiler) clean(s string) (string, errors.Error) { file := path.Clean(s) if file != s { return file, errors.Newf(c.pos, "path not normalized, use %q instead", file) } if path.IsAbs(file) { return "", errors.Newf(c.pos, "only relative files are allowed") } if file == ".." || strings.HasPrefix(file, "../") { return "", errors.Newf(c.pos, "cannot refer to parent directory") } return file, nil } // isHidden checks if a file is hidden on Windows. We do not return an error // if the file does not exist and will check that elsewhere. func (c *compiler) isHidden(file string) bool { return strings.HasPrefix(file, ".") || strings.Contains(file, "/.") } func (c *compiler) decodeFile(file, scope string, schema adt.Value) (adt.Expr, errors.Error) { // Do not use the most obvious filetypes.Input in order to disable "auto" // mode. f, err := filetypes.ParseFileAndType(file, scope, filetypes.Def) if err != nil { return nil, errors.Promote(err, "invalid file type") } // Open and pre-load the file system using fs.FS, instead of relying r, err := c.fs.Open(file) if err != nil { return nil, errors.Newf(c.pos, "open %v: no such file or directory", file) } defer r.Close() info, err := r.Stat() if err != nil { return nil, errors.Promote(err, "failed to decode file") } if info.IsDir() { return nil, errors.Newf(c.pos, "cannot embed directories") } f.Source = r // TODO: this really should be done at the start of the build process. // c.b.ExternFiles = append(c.b.ExternFiles, f) config := &encoding.Config{ // TODO: schema is currently the wrong schema, which is a bug in // internal/core/runtime. There is also an outstanding design choice: // do we imply the schema from the schema of the current field, or do // we explicitly enable schema-based encoding with a "schema" argument. // In the case of YAML it seems to be better to be explicit. In the case // of textproto it seems to be more convenient to do it implicitly. // Schema: value.Make(c.opCtx, schema), } d := encoding.NewDecoder(c.runtime, f, config) if err := d.Err(); err != nil { return nil, errors.Promote(err, "failed to decode file") } defer d.Close() n := d.File() if d.Next(); !d.Done() { return nil, errors.Newf(c.pos, "streaming not implemented: found more than one value in file") } switch f.Encoding { case build.CUE: return nil, errors.Newf(c.pos, "encoding %q not (yet) supported", f.Encoding) case build.JSONL: return nil, errors.Newf(c.pos, "encoding %q not (yet) supported: requires support for streaming", f.Encoding) case build.BinaryProto, build.TextProto: return nil, errors.Newf(c.pos, "encoding %q not (yet) supported: requires support for schema-guided decoding", f.Encoding) } val := c.runtime.BuildFile(n) if err := val.Err(); err != nil { return nil, errors.Promote(err, "failed to build file") } _, v := value.ToInternal(val) return v, nil } cue-lang-cue-db9cc73/cue/interpreter/embed/embed_test.go000066400000000000000000000023701474664451600233370ustar00rootroot00000000000000// Copyright 2024 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package embed import "testing" func TestIsHidden(t *testing.T) { // These test cases are the same for both Unix and Windows. testCases := []struct { path string want bool }{{ path: "", want: false, }, { path: "foo", want: false, }, { path: ".foo", want: true, }, { path: "foo/bar", want: false, }, { path: "foo/.bar", want: true, }, { path: ".foo/bar", want: true, }, { path: "x/.foo/bar", want: true, }} c := &compiler{dir: "/tmp"} for _, tc := range testCases { t.Run(tc.path, func(t *testing.T) { got := c.isHidden(tc.path) if got != tc.want { t.Errorf("isHidden(%q) = %t; want %t", tc.path, got, tc.want) } }) } } cue-lang-cue-db9cc73/cue/interpreter/wasm/000077500000000000000000000000001474664451600205665ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/builtin.go000066400000000000000000000066641474664451600225770ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm import ( "cuelang.org/go/cue" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/pkg" "cuelang.org/go/internal/value" ) // generateCallThatReturnsBuiltin returns a call expression to a nullary // builtin that returns another builtin that corresponds to the external // Wasm function declared by the user. name is the name of the function, // args are its declared arguments, scope is a CUE value that represents // the structure into which to resolve the arguments and i is the // loaded Wasm instance that contains the function. // // This function is implemented as a higher-order function to solve a // bootstrapping issue. The user can specifies arbitrary types for the // function's arguments, and these types can be arbitrary CUE types // defined in arbitrary places. This function is called before CUE // evaluation at a time where identifiers are not yet resolved. This // higher-order design solves the bootstrapping issue by deferring the // resolution of identifiers (and selectors, and expressions in general) // until runtime. At compile-time we only generate a nullary builtin // that we call, and being nullary, it does not need to refer to any // unresolved identifiers, rather the identifiers (and selectors) are // saved in the closure that executes later, at runtime. // // Additionally, resolving identifiers (and selectors) requires an // OpContext, and we do not have an OpContext at compile time. With // this higher-order design we get an appropiate OpContext when the // runtime calls the nullary builtin hence solving the bootstrapping // problem. func generateCallThatReturnsBuiltin(name string, scope adt.Value, args []string, i *instance) (adt.Expr, error) { // ensure that the function exists before trying to call it. _, err := i.load(name) if err != nil { return nil, err } call := &adt.CallExpr{Fun: &adt.Builtin{ Result: adt.TopKind, Name: name, Func: func(opctx *adt.OpContext, _ []adt.Value) adt.Expr { scope := value.Make(opctx, scope) sig := compileStringsInScope(args, scope) args, result := splitLast(sig) b := &pkg.Builtin{ Name: name, Params: params(args), Result: result.Kind(), Func: cABIFunc(i, name, sig), } return pkg.ToBuiltin(b) }, }} return call, nil } // param converts a CUE value that represents the type of a function // argument into its pkg.Param counterpart. func param(arg cue.Value) pkg.Param { param := pkg.Param{ Kind: arg.IncompleteKind(), } if param.Kind == adt.StructKind || ((param.Kind & adt.NumberKind) != 0) { _, v := value.ToInternal(arg) param.Value = v } return param } // params converts a list of CUE values that represent the types of a // function's arguments into their pkg.Param counterparts. func params(args []cue.Value) []pkg.Param { var params []pkg.Param for _, a := range args { params = append(params, param(a)) } return params } cue-lang-cue-db9cc73/cue/interpreter/wasm/call.go000066400000000000000000000122001474664451600220230ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm import ( "fmt" "cuelang.org/go/cue" "cuelang.org/go/internal/pkg" "github.com/tetratelabs/wazero/api" ) func encBool(b bool) uint64 { if b { return api.EncodeU32(1) } return api.EncodeU32(0) } // encNumber returns the Wasm/System V ABI representation of the number // wrapped into val, which must conform to the type of typ. func encNumber(typ cue.Value, val cue.Value) (r uint64) { ctx := val.Context() _int32 := ctx.CompileString("int32") if _int32.Subsume(typ) == nil { i, _ := val.Int64() return api.EncodeI32(int32(i)) } _int64 := ctx.CompileString("int64") if _int64.Subsume(typ) == nil { i, _ := val.Int64() return api.EncodeI64(i) } _uint32 := ctx.CompileString("uint32") if _uint32.Subsume(typ) == nil { i, _ := val.Uint64() return api.EncodeU32(uint32(i)) } _uint64 := ctx.CompileString("uint64") if _uint64.Subsume(typ) == nil { i, _ := val.Uint64() return i } _float32 := ctx.CompileString("float32") if _float32.Subsume(typ) == nil { f, _ := val.Float64() return api.EncodeF32(float32(f)) } _float64 := ctx.CompileString("float64") if _float64.Subsume(typ) == nil { f, _ := val.Float64() return api.EncodeF64(f) } panic("encNumber: unsupported argument type") } func decBool(v uint64) bool { return api.DecodeU32(v) == 1 } // decNumber decodes the Wasm/System V ABI encoding of the // val number of type typ into a Go value. func decNumber(typ cue.Value, val uint64) (r any) { ctx := typ.Context() _int32 := ctx.CompileString("int32") if _int32.Subsume(typ) == nil { return api.DecodeI32(val) } _uint32 := ctx.CompileString("uint32") if _uint32.Subsume(typ) == nil { return api.DecodeU32(val) } _int64 := ctx.CompileString("int64") if _int64.Subsume(typ) == nil { return int64(val) } _uint64 := ctx.CompileString("uint64") if _uint64.Subsume(typ) == nil { return val } _float32 := ctx.CompileString("float32") if _float32.Subsume(typ) == nil { return api.DecodeF32(val) } _float64 := ctx.CompileString("float64") if _float64.Subsume(typ) == nil { return api.DecodeF64(val) } panic(fmt.Sprintf("unsupported argument type %v (kind %v)", typ, typ.IncompleteKind())) } func encBytes(i *instance, b []byte) *memory { m, _ := i.Alloc(uint32(len(b))) m.WriteAt(b, 0) return m } // cABIFunc implements the Wasm/System V ABI translation. The named // function, which must be loadable by the instance, and must be of // the specified sig type, will be called by the runtime after its // arguments will be converted according to the ABI. The result of the // call will be then also be converted back into a Go value and handed // to the runtime. func cABIFunc(i *instance, name string, sig []cue.Value) func(*pkg.CallCtxt) { // Compute the layout of all encountered structs (arguments // and result) such that we will have it available at the time // of an actual call. argsTyp, resTyp := splitLast(sig) argLayouts := make([]*structLayout, 0, len(argsTyp)) var retLayout *structLayout for _, typ := range argsTyp { switch typ.IncompleteKind() { case cue.StructKind: argLayouts = append(argLayouts, structLayoutVal(typ)) default: argLayouts = append(argLayouts, nil) } } if resTyp.IncompleteKind() == cue.StructKind { retLayout = structLayoutVal(resTyp) } fn, _ := i.load(name) return func(c *pkg.CallCtxt) { argsTyp, resTyp := splitLast(sig) args := make([]uint64, 0, len(argsTyp)) for k, typ := range argsTyp { switch typ.IncompleteKind() { case cue.BoolKind: args = append(args, encBool(c.Bool(k))) case cue.IntKind, cue.FloatKind, cue.NumberKind: args = append(args, encNumber(typ, c.Value(k))) case cue.StructKind: ms := encodeStruct(i, c.Value(k), argLayouts[k]) defer i.FreeAll(ms) args = append(args, uint64(ms[0].ptr)) default: panic(fmt.Sprintf("unsupported argument type %v (kind %v)", typ, typ.IncompleteKind())) } } var retMem *memory if resTyp.IncompleteKind() == cue.StructKind { retMem, _ = i.Alloc(uint32(retLayout.size)) // TODO: add support for structs containing pointers. defer i.Free(retMem) args = append(args, uint64(retMem.ptr)) } if c.Do() { res, err := fn.Call(i.ctx, args...) if err != nil { c.Err = err return } switch resTyp.IncompleteKind() { case cue.BoolKind: c.Ret = decBool(res[0]) case cue.IntKind, cue.FloatKind, cue.NumberKind: c.Ret = decNumber(resTyp, res[0]) case cue.StructKind: c.Ret = decodeStruct(retMem.Bytes(), retLayout) default: panic(fmt.Sprintf("unsupported result type %v (kind %v)", resTyp, resTyp.IncompleteKind())) } } } } cue-lang-cue-db9cc73/cue/interpreter/wasm/doc.go000066400000000000000000000142251474664451600216660ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package wasm allows users to write their own functions and make // them available to CUE via Wasm modules. // // To enable Wasm support, pass the result of [New] to // [cuelang.org/go/cue/cuecontext.New]. Wasm is enabled by default in // the command line tool. // // Wasm is an experimental feature and the interface described in this // document may change in the future. // // # Using Wasm modules in CUE // // To utilize Wasm modules, CUE files need to declare their intent by // specifying a package attribute: // // @extern("wasm") // package p // // Individual functions can then be imported from Wasm modules using // a field attribute: // // add: _ @extern("foo.wasm", abi=c, sig="func(int64, int64): int64") // mul: _ @extern("foo.wasm", abi=c, sig="func(float64, float64): float64") // not: _ @extern("foo.wasm", abi=c, sig="func(bool): bool") // // The first attribute argument specifies the file name of the Wasm // module, which must reside in the same directory as the CUE file // which uses it. The abi indicates the abstract binary interface (ABI) // used by the function (see below) while sig indicates the type // signature of the function. The grammar for sig is: // // list := expr [ { "," expr } ] // func := "func" "(" [ list ] ")" ":" expr // // Where each expr is a valid CUE identifier or selector. // // The specific ABI used may restrict the allowable signatures further. // // By default, the named Wasm module is searched for a function with // the same name as the CUE field that is associated with the attribute. // If you want to import a function under a different name, you can // specify this in the attribute using an optional name parameter, for // example: // // isPrime: _ @extern("bar.wasm", abi=c, name=is_prime, sig="func(uint64): bool") // // # Runtime requirements for Wasm modules // // CUE runs Wasm code in a secure sandbox, which restricts access to // external resources. Therefore, any Wasm code intended for execution // in CUE must be self-contained and cannot have external dependencies. // // All code exported for use by CUE must be free of observable side // effects. The result of a function call must depend only on its // arguments, and no other implicit state. If a function uses global // state, it must do so only in a way that is undetectable from the // outside. For example, a function that caches results to speed up // its future invocations (memoization) is permitted, but a function // that returns a random number is not. // // The CUE runtime may run different function invocations in different // Wasm runtime instances, so Wasm code must not depend on the existence // of shared state between different function invocations. // // Wasm code must always terminate and return a result. // // Failure to provide the above guarantees will break the internal // logic of CUE and will cause the CUE evaluation to be undefined. // // The CUE runtime may try to detect violations of the above rules, // but it cannot provide any guarantees that violations will be detected. // It is the responsability of the programmer to comply to the above // requirements. // // # ABI requirements for Wasm modules // // Currently only the [System V ABI] (also known as the C ABI) is // supported. Furthermore, only scalar data types and structs containing // either scalar types or other structs can be exchanged between CUE // and Wasm. Scalar means booleans, sized integers, and sized floats. // The sig field in the attribute refers to these data types by their // CUE names, such as bool, uint16, float64. // // Additionally the Wasm module must export two functions with the // following C type signature: // // void* allocate(int n); // void deallocate(void *ptr, int n); // // Allocate returns a Wasm pointer to a buffer of size n. Deallocate // takes a Wasm pointer and the size of the buffer it points to and // frees it. // // # How to compile Rust for use in CUE // // To compile Rust code into a Wasm module usable by CUE, make sure // you have either the wasm32-unknown-unknown or wasm32-wasi targets // installed: // // rustup target add wasm32-wasi // // Note that even with wasm32-wasi, you should assume a [no_std] // environment. Even though CUE can load [WASI] modules, the loaded // modules do not currently have access to a WASI environment. This // might change in the future. // // Compile your Rust crate using a cdynlib crate type as your [cargo target] // targeting the installed Wasm target and make sure the functions you // are exporting are using the C ABI, like so: // // #[no_mangle] // pub extern "C" fn mul(a: f64, b: f64) -> f64 { // a * b // } // // The following Rust functions can be used to implement allocate and // deallocate described above: // // #[cfg_attr(all(target_arch = "wasm32"), export_name = "allocate")] // #[no_mangle] // pub extern "C" fn _allocate(size: u32) -> *mut u8 { // allocate(size as usize) // } // // fn allocate(size: usize) -> *mut u8 { // let vec: Vec> = Vec::with_capacity(size); // // Box::into_raw(vec.into_boxed_slice()) as *mut u8 // } // // #[cfg_attr(all(target_arch = "wasm32"), export_name = "deallocate")] // #[no_mangle] // pub unsafe extern "C" fn _deallocate(ptr: u32, size: u32) { // deallocate(ptr as *mut u8, size as usize); // } // // unsafe fn deallocate(ptr: *mut u8, size: usize) { // let _ = Vec::from_raw_parts(ptr, 0, size); // } // // [System V ABI]: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md // [no_std]: https://docs.rust-embedded.org/book/intro/no-std.html // [WASI]: https://wasi.dev // [cargo target]: https://doc.rust-lang.org/cargo/reference/cargo-targets.html package wasm cue-lang-cue-db9cc73/cue/interpreter/wasm/exe_test.go000066400000000000000000000075311474664451600227430ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // TestExe expects cmd/cue to be configured with wasm support, // which it only is with the cuewasm build tag enabled. //go:build cuewasm package wasm_test import ( "io/fs" "os" "path/filepath" stdruntime "runtime" "strings" "testing" "cuelang.org/go/cmd/cue/cmd" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/interpreter/wasm" "cuelang.org/go/cue/parser" "cuelang.org/go/internal/cuetest" "github.com/rogpeppe/go-internal/gotooltest" "github.com/rogpeppe/go-internal/testscript" ) // We are using TestMain because we want to ensure Wasm is enabled and // works as expected with the command-line tool. func TestMain(m *testing.M) { testscript.Main(m, map[string]func(){ "cue": func() { os.Exit(cmd.Main()) }, }) } // TestExe tests Wasm using the command-line tool. func TestExe(t *testing.T) { root := must(filepath.Abs("testdata"))(t) wasmFiles := filepath.Join(root, "cue") p := testscript.Params{ Dir: "testdata/cue", UpdateScripts: cuetest.UpdateGoldenFiles, RequireExplicitExec: true, RequireUniqueNames: true, Setup: func(e *testscript.Env) error { copyWasmFiles(t, e.WorkDir, wasmFiles) e.Vars = append(e.Vars, "CUE_CACHE_DIR="+filepath.Join(e.WorkDir, ".tmp/cache")) return nil }, Condition: cuetest.Condition, } if err := gotooltest.Setup(&p); err != nil { t.Fatal(err) } testscript.Run(t, p) } func copyWasmFiles(t *testing.T, dstDir, srcDir string) { filepath.WalkDir(dstDir, func(path string, d fs.DirEntry, err error) error { if filepath.Ext(path) != ".wasm" { return nil } relPath := must(filepath.Rel(dstDir, path))(t) from := filepath.Join(srcDir, relPath) copyFile(t, path, from) return nil }) } func copyFile(t *testing.T, dst, src string) { buf := must(os.ReadFile(src))(t) err := os.WriteFile(dst, buf, 0664) if err != nil { t.Fatal(err) } } func check(t *testing.T, dir string, got string) { golden := filepath.Join("testdata", dir) + ".golden" if cuetest.UpdateGoldenFiles { os.WriteFile(golden, []byte(got), 0666) } want := string(must(os.ReadFile(golden))(t)) if got != want { t.Errorf("want %v, got %v", want, got) } } func loadDir(t *testing.T, name string) cue.Value { ctx := cuecontext.New(cuecontext.Interpreter(wasm.New())) bi := dirInstance(t, name) return ctx.BuildInstance(bi) } func dirInstance(t *testing.T, name string) *build.Instance { ctx := build.NewContext(build.ParseFile(loadFile)) inst := ctx.NewInstance(name, nil) files := must(os.ReadDir(name))(t) for _, f := range files { if strings.HasSuffix(f.Name(), "cue") { inst.AddFile(filepath.Join(name, f.Name()), nil) } if strings.HasSuffix(f.Name(), "wasm") { f := &build.File{ Filename: f.Name(), } inst.UnknownFiles = append(inst.UnknownFiles, f) } } inst.Complete() return inst } func loadFile(filename string, src any) (*ast.File, error) { return parser.ParseFile(filename, src, parser.ParseFuncs) } func must[T any](v T, err error) func(t *testing.T) T { fail := false if err != nil { fail = true } return func(t *testing.T) T { if fail { _, file, line, _ := stdruntime.Caller(1) file = filepath.Base(file) t.Fatalf("unexpected error at %v:%v: %v", file, line, err) } return v } } cue-lang-cue-db9cc73/cue/interpreter/wasm/extern.go000066400000000000000000000054671474664451600224360ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm import ( "fmt" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/internal" ) // argList returns the types of a function's arguments and result // (specified as an external attribute) as a list of strings. func argList(a *internal.Attr) ([]string, error) { sig, err := sig(a) if err != nil { return nil, err } f, err := parseFunc(sig) if err != nil { return nil, err } return args(f), nil } // sig returns the function signature specified in an external attribute. func sig(a *internal.Attr) (string, error) { sig, ok, err := a.Lookup(1, "sig") if err != nil { return "", err } if !ok { return "", errors.New(`missing "sig" key`) } return sig, nil } func parseFunc(sig string) (*ast.Func, error) { expr, err := parser.ParseExpr("", sig, parser.ParseFuncs) if err != nil { return nil, err } f, ok := expr.(*ast.Func) if !ok { // TODO: once we have position information, make this // error more user-friendly by returning the position. return nil, errors.New("not a function") } for _, arg := range append(f.Args, f.Ret) { switch arg.(type) { case *ast.Ident, *ast.SelectorExpr: continue default: // TODO: once we have position information, make this // error more user-friendly by returning the position. return nil, errors.Newf(token.NoPos, "expected identifier, found %T", arg) } } return f, nil } func args(f *ast.Func) []string { var args []string for _, arg := range append(f.Args, f.Ret) { switch v := arg.(type) { case *ast.Ident: args = append(args, v.Name) case *ast.SelectorExpr: b, _ := format.Node(v) args = append(args, string(b)) default: panic(fmt.Sprintf("unexpected type: %T", v)) } } return args } // compileStringsInScope takes a list of strings, compiles them using // the provided scope, and returns the compiled values. func compileStringsInScope(strs []string, scope cue.Value) []cue.Value { var vals []cue.Value for _, typ := range strs { val := scope.Context().CompileString(typ, cue.Scope(scope)) vals = append(vals, val) } return vals } func splitLast[T any](x []T) ([]T, T) { return x[:len(x)-1], x[len(x)-1] } cue-lang-cue-db9cc73/cue/interpreter/wasm/layout.go000066400000000000000000000167331474664451600224440ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm import ( "encoding/binary" "fmt" "math" "cuelang.org/go/cue" "cuelang.org/go/internal/core/adt" ) // typ is the type (or kind) of an external type. type typ int8 const ( typErr typ = iota typBool typUint8 typUint16 typUint32 typUint64 typInt8 typInt16 typInt32 typInt64 typFloat32 typFloat64 typStruct ) // field represents a name struct field. type field struct { typ from string // the field name } // positionedField represents a struct field with a known location. type positionedField struct { field offset int // memory offset in the parent struct. inner *structLayout // IFF typ==typStruct } // structLayout describes the memory layout of a struct. type structLayout struct { fields []positionedField size int align int } func sizeof(t typ) int { switch t { case typBool, typUint8, typInt8: return 1 case typUint16, typInt16: return 2 case typUint32, typInt32, typFloat32: return 4 case typUint64, typInt64, typFloat64: return 8 } panic("unreachable") } func encodeStruct(i *instance, v cue.Value, l *structLayout) []*memory { buf := make([]byte, l.size) ms := make([]*memory, 1, 2) // cap is 2 for strings and bytes. buf, ms = encode(i, v, l, buf, ms) ms[0] = encBytes(i, buf) return ms } // encodeStruct serializes v into buf according to the layout. func encode(i *instance, v cue.Value, l *structLayout, buf []byte, ms []*memory) ([]byte, []*memory) { for _, f := range l.fields { arg := v.LookupPath(cue.ParsePath(f.from)) switch f.typ { case typBool: b, _ := arg.Bool() if b { buf[f.offset] = 1 } else { buf[f.offset] = 0 } case typUint8: u, _ := arg.Uint64() buf[f.offset] = byte(u) case typUint16: u, _ := arg.Uint64() binary.LittleEndian.PutUint16(buf[f.offset:], uint16(u)) case typUint32: u, _ := arg.Uint64() binary.LittleEndian.PutUint32(buf[f.offset:], uint32(u)) case typUint64: u, _ := arg.Uint64() binary.LittleEndian.PutUint64(buf[f.offset:], u) case typInt8: u, _ := arg.Int64() buf[f.offset] = byte(u) case typInt16: u, _ := arg.Int64() binary.LittleEndian.PutUint16(buf[f.offset:], uint16(u)) case typInt32: u, _ := arg.Int64() binary.LittleEndian.PutUint32(buf[f.offset:], uint32(u)) case typInt64: u, _ := arg.Int64() binary.LittleEndian.PutUint64(buf[f.offset:], uint64(u)) case typFloat32: x, _ := arg.Float64() binary.LittleEndian.PutUint32(buf[f.offset:], math.Float32bits(float32(x))) case typFloat64: x, _ := arg.Float64() binary.LittleEndian.PutUint64(buf[f.offset:], math.Float64bits(x)) case typStruct: encode(i, arg, f.inner, buf[f.offset:], ms) default: panic(fmt.Sprintf("unsupported argument %v (kind %v)", v, v.IncompleteKind())) } } return buf, ms } // decodeStruct takes the binary representation of a struct described // by the layout and returns its Go representation as a map. func decodeStruct(buf []byte, l *structLayout) map[string]any { m := make(map[string]any) for _, f := range l.fields { switch f.typ { case typBool: u := buf[f.offset] if u == 1 { m[f.from] = true } else { m[f.from] = false } case typUint8: u := buf[f.offset] m[f.from] = u case typUint16: u := binary.LittleEndian.Uint16(buf[f.offset:]) m[f.from] = u case typUint32: u := binary.LittleEndian.Uint32(buf[f.offset:]) m[f.from] = u case typUint64: u := binary.LittleEndian.Uint64(buf[f.offset:]) m[f.from] = u case typInt8: u := buf[f.offset] m[f.from] = int8(u) case typInt16: u := binary.LittleEndian.Uint16(buf[f.offset:]) m[f.from] = int16(u) case typInt32: u := binary.LittleEndian.Uint32(buf[f.offset:]) m[f.from] = int32(u) case typInt64: u := binary.LittleEndian.Uint64(buf[f.offset:]) m[f.from] = int64(u) case typFloat32: u := binary.LittleEndian.Uint32(buf[f.offset:]) m[f.from] = math.Float32frombits(u) case typFloat64: u := binary.LittleEndian.Uint64(buf[f.offset:]) m[f.from] = math.Float64frombits(u) case typStruct: to := f.offset + f.inner.size m[f.from] = decodeStruct(buf[f.offset:to], f.inner) default: panic(fmt.Sprintf("unsupported argument type: %v", f.typ)) } } return m } func align(x, n int) int { return (x + n - 1) & ^(n - 1) } // structLayoutVal returns the System V (C ABI) memory layout of the // struct expressed by t. func structLayoutVal(t cue.Value) *structLayout { if t.IncompleteKind() != adt.StructKind { panic("expected CUE struct") } var sl structLayout off, size := 0, 0 for i, _ := t.Fields(cue.Attributes(true)); i.Next(); { f := i.Value() path := i.Selector().String() switch f.IncompleteKind() { case adt.StructKind: inner := structLayoutVal(f) off = align(off, inner.align) lval := positionedField{ field: field{ typ: typStruct, from: path, }, offset: off, inner: inner, } sl.fields = append(sl.fields, lval) off += inner.size case cue.BoolKind, cue.IntKind, cue.FloatKind, cue.NumberKind: typ := typVal(f) size = sizeof(typ) off = align(off, size) lval := positionedField{ field: field{ typ: typ, from: path, }, offset: off, } sl.fields = append(sl.fields, lval) off += size default: panic(fmt.Sprintf("unsupported argument type %v (kind %v)", f, f.IncompleteKind())) } } // The alignment of a struct is the maximum alignment of its // constituent fields. maxalign := 0 for _, f := range sl.fields { if f.typ == typStruct { if f.inner.align > maxalign { maxalign = f.inner.align } continue } if sizeof(f.typ) > maxalign { maxalign = sizeof(f.typ) } } sl.size = align(off, maxalign) sl.align = maxalign return &sl } func typVal(v cue.Value) typ { switch v.IncompleteKind() { case cue.BoolKind: return typBool case cue.IntKind, cue.FloatKind, cue.NumberKind: return typNum(v) default: panic(fmt.Sprintf("unsupported argument type %v (kind %v)", v, v.IncompleteKind())) } } func typNum(t cue.Value) typ { ctx := t.Context() _int8 := ctx.CompileString("int8") if _int8.Subsume(t) == nil { return typInt8 } _uint8 := ctx.CompileString("uint8") if _uint8.Subsume(t) == nil { return typUint8 } _int16 := ctx.CompileString("int16") if _int16.Subsume(t) == nil { return typInt16 } _uint16 := ctx.CompileString("uint16") if _uint16.Subsume(t) == nil { return typUint16 } _int32 := ctx.CompileString("int32") if _int32.Subsume(t) == nil { return typInt32 } _uint32 := ctx.CompileString("uint32") if _uint32.Subsume(t) == nil { return typUint32 } _int64 := ctx.CompileString("int64") if _int64.Subsume(t) == nil { return typInt64 } _uint64 := ctx.CompileString("uint64") if _uint64.Subsume(t) == nil { return typUint64 } _float32 := ctx.CompileString("float32") if _float32.Subsume(t) == nil { return typFloat32 } _float64 := ctx.CompileString("float64") if _float64.Subsume(t) == nil { return typFloat64 } panic("unreachable") } cue-lang-cue-db9cc73/cue/interpreter/wasm/runtime.go000066400000000000000000000125561474664451600226110ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm import ( "context" "fmt" "os" "sync" "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" ) // A runtime is a Wasm runtime that can compile, load, and execute // Wasm code. type runtime struct { // ctx exists so that we have something to pass to Wazero // functions, but it's unused otherwise. ctx context.Context wazero.Runtime } func newRuntime() runtime { ctx := context.Background() r := wazero.NewRuntime(ctx) wasi_snapshot_preview1.MustInstantiate(ctx, r) return runtime{ ctx: ctx, Runtime: r, } } // compile takes the name of a Wasm module, and returns its compiled // form, or an error. func (r *runtime) compile(name string) (*module, error) { buf, err := os.ReadFile(name) if err != nil { return nil, fmt.Errorf("can't compile Wasm module: %w", err) } mod, err := r.Runtime.CompileModule(r.ctx, buf) if err != nil { return nil, fmt.Errorf("can't compile Wasm module: %w", err) } return &module{ runtime: r, name: name, CompiledModule: mod, }, nil } // compileAndLoad is a convenience method that compiles a module then // loads it into memory returning the loaded instance, or an error. func (r *runtime) compileAndLoad(name string) (*instance, error) { m, err := r.compile(name) if err != nil { return nil, err } i, err := m.load() if err != nil { return nil, err } return i, nil } // A module is a compiled Wasm module. type module struct { *runtime name string wazero.CompiledModule } // load loads the compiled module into memory, returning a new instance // that can be called into, or an error. Different instances of the // same module do not share memory. func (m *module) load() (*instance, error) { cfg := wazero.NewModuleConfig().WithName(m.name) wInst, err := m.Runtime.InstantiateModule(m.ctx, m.CompiledModule, cfg) if err != nil { return nil, fmt.Errorf("can't instantiate Wasm module: %w", err) } inst := instance{ module: m, instance: wInst, alloc: wInst.ExportedFunction("allocate"), free: wInst.ExportedFunction("deallocate"), } return &inst, nil } // An instance is a Wasm module loaded into memory. type instance struct { // mu serializes access the whole struct. mu sync.Mutex *module instance api.Module // alloc is a guest function that allocates guest memory on // behalf of the host. alloc api.Function // free is a guest function that frees guest memory on // behalf of the host. free api.Function } // load attempts to load the named function from the instance, returning // it if found, or an error. func (i *instance) load(funcName string) (api.Function, error) { i.mu.Lock() defer i.mu.Unlock() f := i.instance.ExportedFunction(funcName) if f == nil { return nil, fmt.Errorf("can't find function %q in Wasm module %v", funcName, i.module.Name()) } return f, nil } // Alloc returns a reference to newly allocated guest memory that spans // the provided size. func (i *instance) Alloc(size uint32) (*memory, error) { i.mu.Lock() defer i.mu.Unlock() res, err := i.alloc.Call(i.ctx, uint64(size)) if err != nil { return nil, fmt.Errorf("can't allocate memory: requested %d bytes", size) } return &memory{ i: i, ptr: uint32(res[0]), len: size, }, nil } // Free frees previously allocated guest memory. func (i *instance) Free(m *memory) { i.mu.Lock() defer i.mu.Unlock() i.free.Call(i.ctx, uint64(m.ptr), uint64(m.len)) } // Free frees several previously allocated guest memories. func (i *instance) FreeAll(ms []*memory) { i.mu.Lock() defer i.mu.Unlock() for _, m := range ms { i.free.Call(i.ctx, uint64(m.ptr), uint64(m.len)) } } // memory is a read and write reference to guest memory that the host // requested. type memory struct { i *instance ptr uint32 len uint32 } // Bytes return a copy of the contents of the guest memory to the host. func (m *memory) Bytes() []byte { m.i.mu.Lock() defer m.i.mu.Unlock() bytes, ok := m.i.instance.Memory().Read(m.ptr, m.len) if !ok { panic(fmt.Sprintf("can't read %d bytes from Wasm address %#x", m.len, m.ptr)) } return append([]byte{}, bytes...) } // WriteAt writes p at the given relative offset within m. // It panics if buf doesn't fit into m, or if off is out of bounds. func (m *memory) WriteAt(p []byte, off int64) (int, error) { if (off < 0) || (off >= 1<<32-1) { panic(fmt.Sprintf("can't write %d bytes to Wasm address %#x", len(p), m.ptr)) } m.i.mu.Lock() defer m.i.mu.Unlock() ok := m.i.instance.Memory().Write(m.ptr+uint32(off), p) if !ok { panic(fmt.Sprintf("can't write %d bytes to Wasm address %#x", len(p), m.ptr)) } return len(p), nil } // Args returns a memory in the form of pair of arguments directly // passable to Wasm. func (m *memory) Args() []uint64 { return []uint64{uint64(m.ptr), uint64(m.len)} } cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/000077500000000000000000000000001474664451600223775ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/000077500000000000000000000000001474664451600231535ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/basic.txtar000066400000000000000000000011331474664451600253160ustar00rootroot00000000000000# Test basic Wasm functionality that uses core Wasm types. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p add: _ @extern("basic.wasm", abi=c, sig="func(int64, int64): int64") mul: _ @extern("basic.wasm", abi=c, sig="func(float64, float64): float64") not: _ @extern("basic.wasm", abi=c, sig="func(bool): bool") x0: add(1, 2) x1: add(-1, 2) x2: add(100, 1) y0: mul(3.0, 5.0) y1: mul(-2.5, 3.37) y2: mul(1.234, 5.678) z: not(true) -- basic.wasm -- -- out/wasm -- add: add mul: mul not: not() x0: 3 x1: 1 x2: 101 y0: 15.0 y1: -8.425 y2: 7.006652 z: false cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/basic.wasm000077500000000000000000000005001474664451600251230ustar00rootroot00000000000000asm`~~~`|||`A A A 7memoryaddmulnot __data_end __heap_base   |    As +nameaddmulnot__stack_pointerM producerslanguageRust processed-byrustc1.75.0 (82e1608df 2023-12-21),target_features+mutable-globals+sign-extcue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/basic1.wasm000077500000000000000000000006521474664451600252140ustar00rootroot00000000000000asm`~`~~`A A A ?memoryis_primefactneg32 __data_end __heap_base uC~B! B BV!@@  Q  ! B|"! PE B|!  Z '~B!@@ BQ  ~! B|!  A k 3nameis_primefactneg32__stack_pointerM producerslanguageRust processed-byrustc1.75.0 (82e1608df 2023-12-21),target_features+mutable-globals+sign-extcue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/complex.txtar000066400000000000000000000012771474664451600257150ustar00rootroot00000000000000# Check that we can pass to Wasm structs that have holes in them. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p cornucopia: _ @extern("struct.wasm", abi=c, sig="func(#cornucopia): int64") #cornucopia: { b: bool n0: int16 n1: uint8 n2: int64 } _c0: {b: true, n0: 10, n1: 20, n2: 30} _c1: {b: false, n0: 1, n1: 2, n2: 3} _c2: {b: false, n0: -1, n1: 0, n2: 100} _c3: {b: false, n0: -15000, n1: 10, n2: -10000000} c0: cornucopia(_c0) c1: cornucopia(_c1) c2: cornucopia(_c2) c3: cornucopia(_c3) -- struct.wasm -- -- out/wasm -- cornucopia: cornucopia() #cornucopia: { b: bool n0: int16 n1: uint8 n2: int64 } c0: 42 c1: 6 c2: 99 c3: -10014990 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/def.txtar000066400000000000000000000015341474664451600250000ustar00rootroot00000000000000# Ensure that we have Wasm functionality in cue def. #cuecmd exec cue def -E cmp stdout out/cue-def-stdout -- a.cue -- @extern("wasm") package p add: _ @extern("basic.wasm", abi=c, sig="func(int64, int64): int64") x0: add(1, 2) x1: add(-1, 2) -- b.cue -- @extern("wasm") package p isPrime: _ @extern("basic1.wasm", abi=c, name=is_prime, sig="func(uint64): bool") fact: _ @extern("basic1.wasm", abi=c, sig="func(uint64): uint64") b1: isPrime(127) c1: fact(7) -- basic.wasm -- -- basic1.wasm -- -- out/cue-def-stdout -- package p add: add() @extern("basic.wasm", abi=c, sig="func(int64, int64): int64") x0: add(1, 2) isPrime: is_prime() @extern("basic1.wasm", abi=c, name=is_prime, sig="func(uint64): bool") fact: fact() @extern("basic1.wasm", abi=c, sig="func(uint64): uint64") b1: isPrime(127) x1: add(-1, 2) c1: fact(7) cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/default.txtar000066400000000000000000000004431474664451600256640ustar00rootroot00000000000000# Check that default values are resolved correctly. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p add: _ @extern("basic.wasm", abi=c, sig="func(int64, int64): int64") x0: add(*1 | string, *2 | string) -- basic.wasm -- -- out/wasm -- add: add x0: 3cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/empty.wasm000066400000000000000000000000001474664451600251700ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/error.txtar000066400000000000000000000011641474664451600253720ustar00rootroot00000000000000# Checks that invalid function signatures is an error. #error ! exec cue export -E --out cue cmp stderr out/wasm -- a.cue -- @extern("wasm") package p add: _ @extern("basic.wasm", abi=c, sig="func(int64, int64)") mul: _ @extern("basic.wasm", abi=c, sig="func(float64, float64): []") not: _ @extern("basic.wasm", abi=c, sig="func(*): bool") -- basic.wasm -- -- out/wasm -- @wasm: invalid function signature: expected ':', found newline: ./a.cue:4:8 @wasm: invalid function signature: expected identifier, found *ast.ListLit: ./a.cue:5:8 @wasm: invalid function signature: expected operand, found ')': ./a.cue:6:8 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/missing.txtar000066400000000000000000000006541474664451600257150ustar00rootroot00000000000000# Check that missing Wasm modules cause errors. #error ! exec cue export -E --out cue cmp stderr out/wasm -- a.cue -- @extern("wasm") package p add: _ @extern("foo.wasm", abi=c, sig="func(int64, int64): int64") sub: _ @extern("foo.wasm1", abi=c, sig="func(int64, int64): int64") x: add(1, 2) -- out/wasm -- @wasm: load "foo.wasm": file not found: ./a.cue:4:8 @wasm: load "foo.wasm1": invalid file name: ./a.cue:5:8 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/multiple.txtar000066400000000000000000000014731474664451600260770ustar00rootroot00000000000000# Check that we can load multiple Wasm modules into the same CUE package. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p neg32: _ @extern("basic1.wasm", abi=c, sig="func(int32): int32") add: _ @extern("basic.wasm", abi=c, sig="func(int64, int64): int64") x0: add(1, 2) x1: add(-1, 2) x2: add(100, 1) -- b.cue -- @extern("wasm") package p isPrime: _ @extern("basic1.wasm", abi=c, name=is_prime, sig="func(uint64): bool") fact: _ @extern("basic1.wasm", abi=c, sig="func(uint64): uint64") a0: neg32(42) b1: isPrime(127) b2: isPrime(128) c1: fact(7) c2: fact(9) -- basic.wasm -- -- basic1.wasm -- -- out/wasm -- isPrime: is_prime() fact: fact() a0: -42 b1: true b2: false c1: 5040 c2: 362880 neg32: neg32() add: add x0: 3 x1: 1 x2: 101 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/nested.txtar000066400000000000000000000022411474664451600255200ustar00rootroot00000000000000# Check that we can pass nested structs to Wasm. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p #vector2: { x: float64 y: float64 } #foo: { b: bool bar: #bar } #bar: { b: bool baz: #baz n: uint16 } #baz: { vec: #vector2 } mag: _ @extern("struct.wasm", abi=c, name=magnitude_foo, sig="func(#foo): float64") mb0: mag({b: false, bar: {b: true, baz: {vec: {x: 1, y: 1}}, n: 0}}) mb1: mag({b: true, bar: {b: false, baz: {vec: {x: 3, y: 4}}, n: 1}}) mb2: mag({b: false, bar: {b: true, baz: {vec: {x: 12, y: 35}}, n: 5}}) mb3: mag({b: false, bar: {b: false, baz: {vec: {x: 3.33, y: 5.55}}, n: 110}}) -- struct.wasm -- -- out/wasm -- #vector2: { x: float64 y: float64 } #foo: { b: bool bar: { b: bool baz: { vec: { x: float64 y: float64 } } n: uint16 } } #bar: { b: bool baz: { vec: { x: float64 y: float64 } } n: uint16 } #baz: { vec: { x: float64 y: float64 } } mag: magnitude_foo() mb0: 1.4142135623730951 mb1: 5.0 mb2: 37.0 mb3: 6.472356603278283 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/noload.txtar000066400000000000000000000002451474664451600255140ustar00rootroot00000000000000# Check that we can enable Wasm without using it. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p x: 42 -- out/wasm -- x: 42 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/nopackage.txtar000066400000000000000000000004731474664451600261730ustar00rootroot00000000000000# Checks that we can't load Wasm without enabling it at the package-level. #error ! exec cue eval -E --out cue cmp stderr out/wasm -- a.cue -- package p add: _ @extern("foo.wasm", abi=c, sig="func(int64, int64): int64") x00: add(1, 2) -- out/wasm -- x00: cannot call non-function add (type _): ./a.cue:5:6 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/struct.txtar000066400000000000000000000030631474664451600255650ustar00rootroot00000000000000exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p import "math" #vector2: { x: float64 y: float64 } magnitude2: _ @extern("struct.wasm", abi=c, sig="func(#vector2): float64") magnitude3: _ @extern("struct.wasm", abi=c, sig="func(#vector3): float64") _v0: {x: 1, y: 1} _v1: {x: math.Sqrt2, y: math.Sqrt2} _v2: {x: 123.456, y: 789.012} m0: magnitude2(_v0) m1: magnitude2(_v1) m2: magnitude2(_v2) normalize2: _ @extern("struct.wasm", abi=c, sig="func(#vector2): #vector2") n2: normalize2(_v1) n2m: magnitude2(n2) #vector3: { x: float64 y: float64 z: float64 } _v3: {x: 1, y: 1, z: 1} _v4: {x: 0, y: 2, z: 2} _v5: {x: 3.84900179459750509672765853667971637098401167513417917345734884322651781535288897129144, y: 3.84900179459750509672765853667971637098401167513417917345734884322651781535288897129144, z: 3.84900179459750509672765853667971637098401167513417917345734884322651781535288897129144} m3: magnitude3(_v3) m4: magnitude3(_v4) m5: magnitude3(_v5) double3: _ @extern("struct.wasm", abi=c, sig="func(#vector3): #vector3") d4: double3(_v4) -- struct.wasm -- -- out/wasm -- #vector2: { x: float64 y: float64 } magnitude2: magnitude2() magnitude3: magnitude3() m0: 1.4142135623730951 m1: 2.0 m2: 798.6121211702211 normalize2: normalize2 n2: { x: 0.7071067811865476 y: 0.7071067811865476 } n2m: 1.0 #vector3: { x: float64 y: float64 z: float64 } m3: 1.7320508075688772 m4: 2.8284271247461903 m5: 6.666666666666667 double3: double3 d4: { x: 0.0 y: 4.0 z: 4.0 } cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/struct.wasm000077500000000000000000000346651474664451600254110ustar00rootroot00000000000000asm2 ``````|`~``! p A A A  memoryallocate deallocate magnitude2 magnitude3 normalize2double3 cornucopia magnitude_foo __data_end __heap_base A    H@@@ E AL A-A "E    A  #Ak"$@@ AjAv"Aj"AI A(6  AjAȁAȁ!A (6  A6  AtAj"(6  A j AjA!  ( 6 Aj$  #Ak"$@ E @ AjAvAj"AI A(6 AjAȁAA (6  A6  AtAj"(6 A j AjA  ( 6 Aj$ N#A k"$ AjB7 A6 A6 Aȁ6 AjA @ E  | +"  +"  %| +"  +"  +"  .| +" +"   "9  9 1| +" 9 +" 9 +" 9 '~B*!@ - 1 2| )|!  | Aj+"  Aj+"  L#A k"$ A;  6  6 AȀ6 Aȁ6 A j "@ ("     BŀK7 B7 \#A k"$ A jB7 A6 Aȁ6 A+6 A؀6 Aj6 A   D A j(!@@ (  - - - - zAA("Aj6@ AH A-Aq AA:AA(Aj6A(AL AA: E  #Ak"$  ("(6 Aj" l"A AK"A A jAȁAȁ!  ( 6@@  A!  B7   AtjAr6A! 6 6 Aj$ #Ak"$@    " Aj   ( A! ( ( " (6  6    ! Aj$   Aj!A!A k! At! (! @@ E !@@@@ (" Aq (A|q" Aj" k I @  (AtjAj k q" M (!  q   A|q6 (! !  A! A6 Axj" B7 (A|q6@ (" A|q"E A  Aq" E (Aq r6 (Aq!  r6  (A~q6  ("Aq r" 6 Aq  (!   A~q6@@ (A|q" A!  A -Aq! @ -AqE (Ar6  6 !  A}q6 (Ar! Ar6 Aj!   6 @ ("A|q"E A  Aq"E  (Aq (A|qr6 (! @ ("A|q"E  (Aq A|qr6 (! (! Aq6 Aq6  n@@ At" AtAj"  KAj"Av@"AG A!A!  At"B7   A|qjAr6A! 6 6 A A    A  A6 Axj" (A~q6@  E @@ A|j(A|q"E -Aq  -AqE   (Ar6 ("A|q"E A  Aq"E  -Aq  (A|q6  Ar6  (6  6 A library/alloc/src/raw_vec.rscapacity overflow!called `Option::unwrap()` on a `None` valuelibrary/std/src/panicking.rs  .debug_abbrev%B9.n: ; .@n: ;?1X Y W %BU.n: ; .@n: ; ? .@n: ; 6 ? 1UX Y W .@n: ; .@n: ; .@: ;6 ?1X YW 1X Y W 1X YW .@n: ;.n: ;? 1X YW 1X Y W 1UX YW 1UX YW .@n: ; %B.n: ;  .: ; 6 ? .debug_infox, NJai'4AN" 5#j& J*+L[4:-'@ \x  k    ai'4Ad  j+ >?&b"nQb l D ,  9>KPJAA"    ^z(^SW^ /E^ X J" =" :" q,8~P h        [c V M      `   7  ; ?7 ; es$ $- JO_J\WR u V) aiy'  5|V       \ g\ gL  L  <  >SDU! .debug_rangesa b ]^ .debug_str{impl#0}{closure#0}anyLocalKeycapacity_overflownew_constpanic_abortpanic_counthintpanic_fmtsysArgumentslocksas_strptrinternal_constructorbegin_panic_handlerpanic_infoPanicInfosys_commonoptionOptionwasmmemcellCelllocalrust_panic_with_hookfinished_panic_hookrwlockRwLockpanickingAtomicUsizeincreasecoremessageforce_no_backtracestdrust_begin_unwindcan_unwindfetch_addthreadallocsyncrust_panic__rust_start_panicatomicraw_vec_ZN3std3sys4wasm5locks6rwlock6RwLock4read17hdf138ea3af16061fE_ZN3std6thread5local17LocalKey$LT$T$GT$4with17h093ab48bde9f882eE_ZN11panic_abort18__rust_start_panic5abort17h1ff73b140a8f211eE_ZN3std9panicking19begin_panic_handler28_$u7b$$u7b$closure$u7d$$u7d$17h823c80ef219a166dE_ZN3std9panicking11panic_count8increase17h37095046341f424dE_ZN4core3fmt9Arguments9new_const17hb454a8fd588bd98cE_ZN4core5panic10panic_info9PanicInfo18force_no_backtrace17h1993db34b12a9e5cE_ZN5alloc7raw_vec17capacity_overflow17hfd18578094e5282cE_ZN3std6thread5local17LocalKey$LT$T$GT$8try_with17ha1efa37921fb16cbE_ZN4core4sync6atomic10atomic_add17had440d2d11c5bb7aE_ZN4core3ptr5write17h142fa5e0ea02133aE_ZN36_$LT$T$u20$as$u20$core..any..Any$GT$7type_id17h3f1658fbcb5f23d9E_ZN4core3fmt9Arguments6as_str17h75f0b001b62aa949E_ZN4core5panic10panic_info9PanicInfo20internal_constructor17h7573a8fb3d479239E_ZN4core5panic10panic_info9PanicInfo10can_unwind17h303745b8319a4ee8E_ZN4core9panicking9panic_fmt17hd79411a297d06dc8E_ZN4core9panicking5panic17hd37d8d0a98259c88E_ZN4core4cell13Cell$LT$T$GT$3set17h5b04885f62d36f38E_ZN3std9panicking11panic_count8increase28_$u7b$$u7b$closure$u7d$$u7d$17hd30c6fe76018d838E_ZN4core4sync6atomic11AtomicUsize9fetch_add17h52ac984dde38c9d7E_ZN4core4cell13Cell$LT$T$GT$3get17ha4dac3ba44b89657E_ZN3std10sys_common9backtrace26__rust_end_short_backtrace17hcc7222b556723586E_ZN3std6thread5local17LocalKey$LT$T$GT$8try_with17h0189baea3086f656E_ZN4core4hint9black_box17h781967a6817e9e93E_ZN4core5panic10panic_info9PanicInfo7message17h5421a99d61af5a83E_ZN3std9panicking20rust_panic_with_hook17h62090d3fc0630473E_ZN3std4sync6rwlock15RwLock$LT$T$GT$4read17h08e624609b594823E_ZN4core3ptr37drop_in_place$LT$core..fmt..Error$GT$17h9152df636f15f3d2E_ZN4core4cell13Cell$LT$T$GT$7replace17h736a5cc1ed61b901E_ZN3std9panicking11panic_count19finished_panic_hook28_$u7b$$u7b$closure$u7d$$u7d$17hbbfc6345232069f0E_ZN4core6option15Option$LT$T$GT$6unwrap17h8364da5c89e521e0E_ZN4core4cell13Cell$LT$T$GT$3get17ha781afd58ca76db0E_ZN3std6thread5local17LocalKey$LT$T$GT$4with17h7c7567c441adc670E_ZN3std9panicking11panic_count19finished_panic_hook17h0fb215cd9d2fcb20E_ZN4core3mem7replace17hea879efc3fc42a10Eunwrap<&core::fmt::Arguments>drop_in_placereadatomic_addgettype_idtry_with, std::panicking::panic_count::increase::{closure_env#0}, core::option::Option>set<(usize, bool)>get<(usize, bool)>write<(usize, bool)>replace<(usize, bool)>black_box<()>try_with, std::panicking::panic_count::finished_panic_hook::{closure_env#0}, ()>__rust_end_short_backtrace/rustc/82e1608dfa6e0b5569232559e3d385fea5a93112library/alloc/src/lib.rs/@/alloc.6c9c8ba8821e693a-cgu.0library/std/src/lib.rs/@/std.a220717b168087b5-cgu.0library/core/src/lib.rs/@/core.f5320dfba861e725-cgu.0library/panic_abort/src/lib.rs/@/panic_abort.4ef0503942fe3991-cgu.0clang LLVM (rustc version 1.75.0 (82e1608df 2023-12-21)).debug_pubnamesg|&core+fmt0Arguments5new_constEallocJraw_vecOcapacity_overflow(|&core0panic_info5PanicInfo:internal_constructorIpanickingNpanic_fmtwpanicptrdrop_in_placeany{impl#0}type_idfmtArgumentsnew_constt~&std+panicking0rust_paniclbegin_panic_handler{closure#0}#panic_count5increase[finished_panic_hookirust_panic_with_hooksys_commonbacktrace__rust_end_short_backtrace.thread3local8LocalKey=try_with, std::panicking::panic_count::increase::{closure_env#0}, core::option::Option>Jwith, std::panicking::panic_count::increase::{closure_env#0}, core::option::Option>Vtry_with, std::panicking::panic_count::finished_panic_hook::{closure_env#0}, ()>cwith, std::panicking::panic_count::finished_panic_hook::{closure_env#0}, ()>rsyswwasm|locksreadsyncrwlockRwLockreadcorepanicpanic_infoPanicInfomessagecan_unwindforce_no_backtraceoptionOptionunwrap<&core::fmt::Arguments>hintblack_box<()>"fmt'Arguments,as_str@atomicEatomic_addRAtomicUsizeWfetch_addgcelllCellqget<(usize, bool)>getreplace<(usize, bool)>set<(usize, bool)>ptrwrite<(usize, bool)>mem?@panic_abort(abort5__rust_start_panicX.debug_pubtypes||~@ .debug_linep library/alloc/srclibrary/core/src/fmtlibrary/core/srcraw_vec.rsmod.rspanic.rs ~t#( library/core/srclibrary/core/src/paniclibrary/core/src/ptrlibrary/core/src/fmtpanicking.rspanic_info.rsmod.rsany.rsmod.rs3 q'    t*~ ~  library/panic_abort/srclibrary/std/srclibrary/core/src/paniclibrary/core/srclibrary/std/src/sys_commonlibrary/core/src/fmtlibrary/core/src/synclibrary/core/src/ptrlibrary/std/src/sys/wasm/../unsupported/lockslibrary/std/src/threadlibrary/core/src/memlibrary/std/src/synclib.rspanicking.rspanic_info.rsoption.rsbacktrace.rshint.rsmod.rsatomic.rscell.rsmod.rsrwlock.rs local.rs mod.rs rwlock.rs   etLxt     ~tf| X X Xzt   X X a i|< .  J yt    yt.  |k<   J{t`yt<6 library/panic_abort/srclib.rsname allocateg_ZN72_$LT$wee_alloc..WeeAlloc$u20$as$u20$core..alloc..global..GlobalAlloc$GT$5alloc17hc997baa537d6eacfEi_ZN72_$LT$wee_alloc..WeeAlloc$u20$as$u20$core..alloc..global..GlobalAlloc$GT$7dealloc17hefa5561c372b7dd2E8_ZN5alloc7raw_vec17capacity_overflow17hfd18578094e5282cE deallocate magnitude2 magnitude3 normalize2double3 cornucopia magnitude_foo 0_ZN4core9panicking9panic_fmt17hd79411a297d06dc8E rust_begin_unwind G_ZN4core3ptr37drop_in_place$LT$core..fmt..Error$GT$17h9152df636f15f3d2EE_ZN36_$LT$T$u20$as$u20$core..any..Any$GT$7type_id17h3f1658fbcb5f23d9E,_ZN4core9panicking5panic17hd37d8d0a98259c88E rust_panicM_ZN3std10sys_common9backtrace26__rust_end_short_backtrace17hcc7222b556723586EX_ZN3std9panicking19begin_panic_handler28_$u7b$$u7b$closure$u7d$$u7d$17h823c80ef219a166dE;_ZN3std9panicking20rust_panic_with_hook17h62090d3fc0630473E_ZN88_$LT$wee_alloc..size_classes..SizeClassAllocPolicy$u20$as$u20$wee_alloc..AllocPolicy$GT$22new_cell_for_free_list17h389adbb3108ecd23E4_ZN9wee_alloc17alloc_with_refill17ha665bdbde1fb96caE2_ZN9wee_alloc15alloc_first_fit17h1cc18d8400927c78EF_ZN9wee_alloc9neighbors18Neighbors$LT$T$GT$6remove17h09e8c8a1561d8ca2ER_ZN4core3ptr48drop_in_place$LT$wee_alloc..LargeAllocPolicy$GT$17h1141011b596d7638Ew_ZN70_$LT$wee_alloc..LargeAllocPolicy$u20$as$u20$wee_alloc..AllocPolicy$GT$22new_cell_for_free_list17hb8c721375b3d82fbEn_ZN70_$LT$wee_alloc..LargeAllocPolicy$u20$as$u20$wee_alloc..AllocPolicy$GT$13min_cell_size17h304de606baaf318dE_ZN70_$LT$wee_alloc..LargeAllocPolicy$u20$as$u20$wee_alloc..AllocPolicy$GT$32should_merge_adjacent_free_cells17h69c257dcf97e216eEd_ZN4core3ptr66drop_in_place$LT$wee_alloc..size_classes..SizeClassAllocPolicy$GT$17hb1fd1447c8f82480E_ZN88_$LT$wee_alloc..size_classes..SizeClassAllocPolicy$u20$as$u20$wee_alloc..AllocPolicy$GT$13min_cell_size17h867c5a88b2f8e830E_ZN88_$LT$wee_alloc..size_classes..SizeClassAllocPolicy$u20$as$u20$wee_alloc..AllocPolicy$GT$32should_merge_adjacent_free_cells17h67c12665b047a777EV_ZN9wee_alloc8WeeAlloc12dealloc_impl28_$u7b$$u7b$closure$u7d$$u7d$17h9e32f845c1e2bec6E__stack_pointer .rodataM producerslanguageRust processed-byrustc1.75.0 (82e1608df 2023-12-21),target_features+mutable-globals+sign-extcue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/cue/unused.txtar000066400000000000000000000005371474664451600255470ustar00rootroot00000000000000# Check that an unused Wasm module does not impact CUE evaluation. exec cue eval -E --out cue cmp stdout out/wasm -- a.cue -- @extern("wasm") package p add: _ @extern("basic.wasm", abi=c, sig="func(int64, int64): int64") x0: add(1, 2) x1: add(-1, 2) x2: add(100, 1) -- basic.wasm -- -- empty.wasm -- -- out/wasm -- add: add x0: 3 x1: 1 x2: 101 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/gen.go000066400000000000000000000027671474664451600235130ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "os" "os/exec" "path/filepath" ) //go:generate go run gen.go func main() { // We do not want to burden our users, not even our developers // with a Rust dependency, so only build the Rust Wasm binaries // if this variable is set. if _, ok := os.LookupEnv("CUE_WASM_BUILD_RUST"); !ok { return } cwd, _ := os.Getwd() src := filepath.Join(cwd, "rust") buildRust(src) target := filepath.Join(src, "target") bins := filepath.Join(target, "wasm32-unknown-unknown", "release") cue := filepath.Join(cwd, "cue") copyWasm(bins, cue) os.RemoveAll(target) } func buildRust(srcDir string) { cmd := exec.Command( "cargo", "build", "--release", "--target", "wasm32-unknown-unknown", ) cmd.Dir = srcDir cmd.Run() } func copyWasm(binDir, wasmDir string) { files, _ := filepath.Glob(filepath.Join(binDir, "*.wasm")) for _, f := range files { os.Rename(f, filepath.Join(wasmDir, filepath.Base(f))) } } cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/000077500000000000000000000000001474664451600233745ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/Cargo.lock000066400000000000000000000034201474664451600253000ustar00rootroot00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "basic" version = "0.1.0" [[package]] name = "basic1" version = "0.1.0" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "memory_units" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] name = "struct" version = "0.1.0" dependencies = [ "wee_alloc", ] [[package]] name = "wee_alloc" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" dependencies = [ "cfg-if", "libc", "memory_units", "winapi", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/Cargo.toml000066400000000000000000000002231474664451600253210ustar00rootroot00000000000000[workspace] members = [ "basic", "basic1", "struct", ] resolver = "2" [profile.release] opt-level = "z" lto = true codegen-units = 1 cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic/000077500000000000000000000000001474664451600244555ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic/Cargo.toml000066400000000000000000000001331474664451600264020ustar00rootroot00000000000000[package] name = "basic" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic/src/000077500000000000000000000000001474664451600252445ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic/src/lib.rs000066400000000000000000000003211474664451600263540ustar00rootroot00000000000000#[no_mangle] pub extern "C" fn add(a: i64, b: i64) -> i64 { a + b } #[no_mangle] pub extern "C" fn mul(a: f64, b: f64) -> f64 { a * b } #[no_mangle] pub extern "C" fn not(x: bool) -> bool { !x } cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic1/000077500000000000000000000000001474664451600245365ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic1/Cargo.toml000066400000000000000000000001341474664451600264640ustar00rootroot00000000000000[package] name = "basic1" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic1/src/000077500000000000000000000000001474664451600253255ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/basic1/src/lib.rs000066400000000000000000000005171474664451600264440ustar00rootroot00000000000000#[no_mangle] pub extern "C" fn is_prime(n: u64) -> bool { for k in 2..n { if n % k == 0 { return false; } } true } #[no_mangle] pub extern "C" fn fact(n: u64) -> u64 { if n == 1 { return 1; } n * fact(n - 1) } #[no_mangle] pub extern "C" fn neg32(x: i32) -> i32 { -x } cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/struct/000077500000000000000000000000001474664451600247205ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/struct/Cargo.toml000066400000000000000000000002001474664451600266400ustar00rootroot00000000000000[package] name = "struct" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] wee_alloc = "0.4.5" cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/struct/src/000077500000000000000000000000001474664451600255075ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/struct/src/lib.rs000066400000000000000000000022511474664451600266230ustar00rootroot00000000000000mod mem; #[repr(C)] pub struct Vector2 { x: f64, y: f64, } #[repr(C)] pub struct Vector3 { x: f64, y: f64, z: f64, } #[no_mangle] pub extern "C" fn magnitude2(v: &Vector2) -> f64 { (v.x.powi(2) + v.y.powi(2)).sqrt() } #[no_mangle] pub extern "C" fn magnitude3(v: &Vector3) -> f64 { (v.x.powi(2) + v.y.powi(2) + v.z.powi(2)).sqrt() } #[no_mangle] pub extern "C" fn normalize2(v: &Vector2) -> Vector2 { let l = magnitude2(v); Vector2 { x: v.x / l, y: v.y / l, } } #[no_mangle] pub extern "C" fn double3(v: &Vector3) -> Vector3 { Vector3 { x: v.x * 2.0, y: v.y * 2.0, z: v.z * 2.0, } } #[repr(C)] pub struct Cornucopia { b: bool, n0: i16, n1: u8, n2: i64, } #[no_mangle] pub extern "C" fn cornucopia(x: &Cornucopia) -> i64 { if x.b { return 42; } return x.n0 as i64 + x.n1 as i64 + x.n2; } #[repr(C)] pub struct Foo { b: bool, bar: Bar, } #[repr(C)] pub struct Bar { b: bool, baz: Baz, n: u16, } #[repr(C)] pub struct Baz { vec: Vector2, } #[no_mangle] pub extern "C" fn magnitude_foo(x: &Foo) -> f64 { magnitude2(&x.bar.baz.vec) } cue-lang-cue-db9cc73/cue/interpreter/wasm/testdata/rust/struct/src/mem.rs000066400000000000000000000014511474664451600266340ustar00rootroot00000000000000extern crate alloc; extern crate core; extern crate wee_alloc; use alloc::vec::Vec; use std::mem::MaybeUninit; #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[cfg_attr(all(target_arch = "wasm32"), export_name = "allocate")] #[no_mangle] pub extern "C" fn _allocate(size: u32) -> *mut u8 { allocate(size as usize) } fn allocate(size: usize) -> *mut u8 { let vec: Vec> = Vec::with_capacity(size); Box::into_raw(vec.into_boxed_slice()) as *mut u8 } #[cfg_attr(all(target_arch = "wasm32"), export_name = "deallocate")] #[no_mangle] pub unsafe extern "C" fn _deallocate(ptr: u32, size: u32) { deallocate(ptr as *mut u8, size as usize); } unsafe fn deallocate(ptr: *mut u8, size: usize) { let _ = Vec::from_raw_parts(ptr, 0, size); } cue-lang-cue-db9cc73/cue/interpreter/wasm/wasm.go000066400000000000000000000100041474664451600220570ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm import ( "path/filepath" "strings" "sync" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/core/adt" coreruntime "cuelang.org/go/internal/core/runtime" ) // interpreter is a [cuecontext.ExternInterpreter] for Wasm files. type interpreter struct{} // New returns a new Wasm interpreter as a [cuecontext.ExternInterpreter] // suitable for passing to [cuecontext.New]. func New() cuecontext.ExternInterpreter { return &interpreter{} } func (i *interpreter) Kind() string { return "wasm" } // NewCompiler returns a Wasm compiler that services the specified // build.Instance. func (i *interpreter) NewCompiler(b *build.Instance, r *coreruntime.Runtime) (coreruntime.Compiler, errors.Error) { return &compiler{ b: b, runtime: r, wasmRuntime: newRuntime(), instances: make(map[string]*instance), }, nil } // A compiler is a [coreruntime.Compiler] // that provides Wasm functionality to the runtime. type compiler struct { b *build.Instance runtime *coreruntime.Runtime wasmRuntime runtime // mu serializes access to instances. mu sync.Mutex // instances maps absolute file names to compiled Wasm modules // loaded into memory. instances map[string]*instance } // Compile searches for a Wasm function described by the given `@extern` // attribute and returns it as an [adt.Builtin] with the given function // name. func (c *compiler) Compile(funcName string, scope adt.Value, a *internal.Attr) (adt.Expr, errors.Error) { baseFile, err := fileName(a) if err != nil { return nil, errors.Promote(err, "invalid attribute") } // TODO: once we have position information, make this // error more user-friendly by returning the position. if !strings.HasSuffix(baseFile, "wasm") { return nil, errors.Newf(token.NoPos, "load %q: invalid file name", baseFile) } file, found := findFile(baseFile, c.b) if !found { return nil, errors.Newf(token.NoPos, "load %q: file not found", baseFile) } inst, err := c.instance(file) if err != nil { return nil, errors.Newf(token.NoPos, "can't load Wasm module: %v", err) } args, err := argList(a) if err != nil { return nil, errors.Newf(token.NoPos, "invalid function signature: %v", err) } builtin, err := generateCallThatReturnsBuiltin(funcName, scope, args, inst) if err != nil { return nil, errors.Newf(token.NoPos, "can't instantiate function: %v", err) } return builtin, nil } // instance returns the instance corresponding to filename, compiling // and loading it if necessary. func (c *compiler) instance(filename string) (inst *instance, err error) { c.mu.Lock() defer c.mu.Unlock() inst, ok := c.instances[filename] if !ok { inst, err = c.wasmRuntime.compileAndLoad(filename) if err != nil { return nil, err } c.instances[filename] = inst } return inst, nil } // findFile searches the build.Instance for the given file name // and reports its full name and whether it was found. func findFile(name string, b *build.Instance) (path string, found bool) { for _, f := range b.OrphanedFiles { if filepath.Base(f.Filename) == name { return f.Filename, true } } return "", false } // fileName returns the file name of the external module specified in a, // which must be an extern attribute. func fileName(a *internal.Attr) (string, error) { file, err := a.String(0) if err != nil { return "", err } return file, nil } cue-lang-cue-db9cc73/cue/interpreter/wasm/wasm_test.go000066400000000000000000000042051474664451600231240ustar00rootroot00000000000000// Copyright 2023 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package wasm_test import ( "fmt" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/cue/interpreter/wasm" "cuelang.org/go/internal/cuetxtar" ) // TestWasm tests Wasm using the API. func TestWasm(t *testing.T) { test := cuetxtar.TxTarTest{ Root: "./testdata/cue", Name: "wasm", } test.Run(t, func(t *cuetxtar.Test) { ctx := cuecontext.New(cuecontext.Interpreter(wasm.New())) if t.HasTag("cuecmd") { // if #cuecmd is set the test is only for the CUE command, // not the API, so skip it. return } bi := t.Instance() v := ctx.BuildInstance(bi) err := v.Validate() if t.HasTag("error") { // if #error is set we're checking for a specific error, // so only print the error then bail out. for _, err := range errors.Errors(err) { t.WriteErrors(err) } return } // we got an unexpected error. print both the error // and the CUE value, to aid debugging. if err != nil { fmt.Fprintln(t, "Errors:") for _, err := range errors.Errors(err) { t.WriteErrors(err) } fmt.Fprintln(t, "") fmt.Fprintln(t, "Result:") } syntax := v.Syntax( cue.Attributes(false), cue.Final(), cue.Definitions(true), cue.ErrorsAsValues(true), ) file, err := astutil.ToFile(syntax.(ast.Expr)) if err != nil { t.Fatal(err) } got, err := format.Node(file, format.UseSpaces(4), format.TabIndent(false)) if err != nil { t.Fatal(err) } fmt.Fprint(t, string(got)) }) } cue-lang-cue-db9cc73/cue/literal/000077500000000000000000000000001474664451600167105ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/literal/doc.go000066400000000000000000000013021474664451600200000ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package literal implements conversions to and from string representations of // basic data types. package literal cue-lang-cue-db9cc73/cue/literal/indent.go000066400000000000000000000020641474664451600205220ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import "strings" // IndentTabs takes a quoted string and reindents it for the given indentation. // If a string is not a multiline string it will return the string as is. func IndentTabs(s string, n int) string { indent := strings.Repeat("\t", n) qi, _, _, err := ParseQuotes(s, s) if err != nil || !qi.multiline || qi.whitespace == indent { return s } search := "\n" + qi.whitespace replace := "\n" + indent return strings.ReplaceAll(s, search, replace) } cue-lang-cue-db9cc73/cue/literal/indent_test.go000066400000000000000000000020641474664451600215610ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "testing" ) func TestIndentTabs(t *testing.T) { testCases := []struct { in string out string }{{ in: `""" foo bar """`, out: `""" foo bar """`, }, { in: `""" foo bar """`, out: `""" foo bar """`, }, { in: `""`, out: `""`, }} for _, tc := range testCases { t.Run("", func(t *testing.T) { got := IndentTabs(tc.in, 3) if got != tc.out { t.Errorf("got %s; want %s", got, tc.out) } }) } } cue-lang-cue-db9cc73/cue/literal/num.go000066400000000000000000000155411474664451600200440ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "github.com/cockroachdb/apd/v3" ) // We avoid cuelang.org/go/internal.Context as that would be an import cycle. var baseContext apd.Context func init() { baseContext = apd.BaseContext baseContext.Precision = 34 } // NumInfo contains information about a parsed numbers. // // Reusing a NumInfo across parses may avoid memory allocations. type NumInfo struct { pos token.Pos src string p int ch byte buf []byte mul Multiplier base byte neg bool UseSep bool isFloat bool err error } // String returns a canonical string representation of the number so that // it can be parsed with math.Float.Parse. func (p *NumInfo) String() string { if len(p.buf) > 0 && p.base == 10 && p.mul == 0 { return string(p.buf) } var d apd.Decimal _ = p.decimal(&d) return d.String() } type decimal = apd.Decimal // Decimal is for internal use. func (p *NumInfo) Decimal(v *decimal) error { return p.decimal(v) } func (p *NumInfo) decimal(v *apd.Decimal) error { if p.base != 10 { _, _, _ = v.SetString("0") b := p.buf if p.buf[0] == '-' { v.Negative = p.neg b = p.buf[1:] } v.Coeff.SetString(string(b), int(p.base)) return nil } _ = v.UnmarshalText(p.buf) if p.mul != 0 { _, _ = baseContext.Mul(v, v, mulToRat[p.mul]) cond, _ := baseContext.RoundToIntegralExact(v, v) if cond.Inexact() { return p.errorf("number cannot be represented as int") } } return nil } // Multiplier reports which multiplier was used in an integral number. func (p *NumInfo) Multiplier() Multiplier { return p.mul } // IsInt reports whether the number is an integral number. func (p *NumInfo) IsInt() bool { return !p.isFloat } // ParseNum parses s and populates NumInfo with the result. func ParseNum(s string, n *NumInfo) error { *n = NumInfo{pos: n.pos, src: s, buf: n.buf[:0]} if !n.next() { return n.errorf("invalid number %q", s) } switch n.ch { case '-': n.neg = true n.buf = append(n.buf, '-') n.next() case '+': n.next() } seenDecimalPoint := false if n.ch == '.' { n.next() seenDecimalPoint = true } err := n.scanNumber(seenDecimalPoint) if err != nil { return err } if n.err != nil { return n.err } if n.p < len(n.src) { return n.errorf("invalid number %q", s) } if len(n.buf) == 0 { n.buf = append(n.buf, '0') } return nil } func (p *NumInfo) errorf(format string, args ...interface{}) error { return errors.Newf(p.pos, format, args...) } // A Multiplier indicates a multiplier indicator used in the literal. type Multiplier byte const ( mul1 Multiplier = 1 + iota mul2 mul3 mul4 mul5 mul6 mul7 mul8 mulBin = 0x10 mulDec = 0x20 K = mulDec | mul1 M = mulDec | mul2 G = mulDec | mul3 T = mulDec | mul4 P = mulDec | mul5 E = mulDec | mul6 Z = mulDec | mul7 Y = mulDec | mul8 Ki = mulBin | mul1 Mi = mulBin | mul2 Gi = mulBin | mul3 Ti = mulBin | mul4 Pi = mulBin | mul5 Ei = mulBin | mul6 Zi = mulBin | mul7 Yi = mulBin | mul8 ) func (p *NumInfo) next() bool { if p.p >= len(p.src) { p.ch = 0 return false } p.ch = p.src[p.p] p.p++ if p.ch == '.' { if len(p.buf) == 0 { p.buf = append(p.buf, '0') } p.buf = append(p.buf, '.') } return true } func (p *NumInfo) digitVal(ch byte) (d int) { switch { case '0' <= ch && ch <= '9': d = int(ch - '0') case ch == '_': p.UseSep = true return 0 case 'a' <= ch && ch <= 'f': d = int(ch - 'a' + 10) case 'A' <= ch && ch <= 'F': d = int(ch - 'A' + 10) default: return 16 // larger than any legal digit val } return d } func (p *NumInfo) scanMantissa(base int) bool { hasDigit := false var last byte for p.digitVal(p.ch) < base { if p.ch != '_' { p.buf = append(p.buf, p.ch) hasDigit = true } last = p.ch p.next() } if last == '_' { p.err = p.errorf("illegal '_' in number") } return hasDigit } func (p *NumInfo) scanNumber(seenDecimalPoint bool) error { p.base = 10 if seenDecimalPoint { p.isFloat = true if !p.scanMantissa(10) { return p.errorf("illegal fraction %q", p.src) } goto exponent } if p.ch == '0' { // int or float p.next() switch p.ch { case 'x', 'X': p.base = 16 // hexadecimal int p.next() if !p.scanMantissa(16) { // only scanned "0x" or "0X" return p.errorf("illegal hexadecimal number %q", p.src) } case 'b': p.base = 2 // binary int p.next() if !p.scanMantissa(2) { // only scanned "0b" return p.errorf("illegal binary number %q", p.src) } case 'o': p.base = 8 // octal int p.next() if !p.scanMantissa(8) { // only scanned "0o" return p.errorf("illegal octal number %q", p.src) } default: // int (base 8 or 10) or float p.scanMantissa(8) if p.ch == '8' || p.ch == '9' { p.scanMantissa(10) if p.ch != '.' && p.ch != 'e' && p.ch != 'E' { return p.errorf("illegal integer number %q", p.src) } } switch p.ch { case 'e', 'E': if len(p.buf) == 0 { p.buf = append(p.buf, '0') } fallthrough case '.': goto fraction } if len(p.buf) > 0 { p.base = 8 } } goto exit } // decimal int or float if !p.scanMantissa(10) { return p.errorf("illegal number start %q", p.src) } fraction: if p.ch == '.' { p.isFloat = true p.next() p.scanMantissa(10) } exponent: switch p.ch { case 'K', 'M', 'G', 'T', 'P': p.mul = charToMul[p.ch] p.next() if p.ch == 'i' { p.mul |= mulBin p.next() } else { p.mul |= mulDec } var v apd.Decimal p.isFloat = false return p.decimal(&v) case 'e', 'E': p.isFloat = true p.next() p.buf = append(p.buf, 'e') if p.ch == '-' || p.ch == '+' { p.buf = append(p.buf, p.ch) p.next() } if !p.scanMantissa(10) { return p.errorf("illegal exponent %q", p.src) } } exit: return nil } var charToMul = map[byte]Multiplier{ 'K': mul1, 'M': mul2, 'G': mul3, 'T': mul4, 'P': mul5, 'E': mul6, 'Z': mul7, 'Y': mul8, } var mulToRat = map[Multiplier]*apd.Decimal{} func init() { d := apd.New(1, 0) b := apd.New(1, 0) dm := apd.New(1000, 0) bm := apd.New(1024, 0) c := apd.BaseContext for i := Multiplier(1); int(i) < len(charToMul); i++ { // TODO: may we write to one of the sources? var bn, dn apd.Decimal _, _ = c.Mul(&dn, d, dm) d = &dn _, _ = c.Mul(&bn, b, bm) b = &bn mulToRat[mulDec|i] = d mulToRat[mulBin|i] = b } } cue-lang-cue-db9cc73/cue/literal/num_test.go000066400000000000000000000072741474664451600211070ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "fmt" "math/big" "strconv" "testing" "cuelang.org/go/cue/token" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" ) func mkInt(i int) NumInfo { return NumInfo{ base: 10, neg: i < 0, buf: []byte(strconv.Itoa(i)), } } func mkFloat(a string) NumInfo { return NumInfo{ base: 10, buf: []byte(a), neg: a[0] == '-', isFloat: true, } } func mkMul(i string, m Multiplier, base byte) NumInfo { return NumInfo{ base: base, mul: m, neg: i[0] == '-', buf: []byte(i), } } func TestNumbers(t *testing.T) { // hk := newInt(testBase, newRepresentation(0, 10, true)).setInt64(100000) testCases := []struct { lit string norm string n NumInfo }{ {"0", "0", mkInt(0)}, {"1", "1", mkInt(1)}, {"+1", "1", mkInt(1)}, {"-1", "-1", mkInt(-1)}, {"100_000", "100000", NumInfo{UseSep: true, base: 10, buf: []byte("100000")}}, {"1.", "1.", mkFloat("1.")}, {"0.", "0.", mkFloat("0.")}, {".0", "0.0", mkFloat("0.0")}, {"012.34", "12.34", mkFloat("12.34")}, {".01", "0.01", mkFloat("0.01")}, {".01e2", "0.01e2", mkFloat("0.01e2")}, {"0.", "0.", mkFloat("0.")}, {"1K", "1000", mkMul("1", K, 10)}, {".5K", "500", mkMul("0.5", K, 10)}, {"1Mi", "1048576", mkMul("1", Mi, 10)}, {"1.5Mi", "1572864", mkMul("1.5", Mi, 10)}, // {"1.3Mi", &bottom{}}, // Cannot be accurately represented. {"1.3G", "1300000000", mkMul("1.3", G, 10)}, {"1.3e+20", "1.3e+20", mkFloat("1.3e+20")}, {"1.3e20", "1.3e20", mkFloat("1.3e20")}, {"1.3e-5", "1.3e-5", mkFloat("1.3e-5")}, {".3e-1", "0.3e-1", mkFloat("0.3e-1")}, {"0e-5", "0e-5", mkFloat("0e-5")}, {"0E-5", "0e-5", mkFloat("0e-5")}, {"5e-5", "5e-5", mkFloat("5e-5")}, {"5E-5", "5e-5", mkFloat("5e-5")}, {"0x1234", "4660", mkMul("1234", 0, 16)}, {"0xABCD", "43981", mkMul("ABCD", 0, 16)}, {"-0xABCD", "-43981", mkMul("-ABCD", 0, 16)}, {"0b11001000", "200", mkMul("11001000", 0, 2)}, {"0b1", "1", mkMul("1", 0, 2)}, {"0o755", "493", mkMul("755", 0, 8)}, {"0755", "493", mkMul("755", 0, 8)}, } n := NumInfo{} for i, tc := range testCases { t.Run(fmt.Sprintf("%d/%+q", i, tc.lit), func(t *testing.T) { if err := ParseNum(tc.lit, &n); err != nil { t.Fatal(err) } n.src = "" n.p = 0 n.ch = 0 if diff := cmp.Diff(n, tc.n, diffOpts...); diff != "" { t.Error(diff) t.Errorf("%#v, %#v\n", n, tc.n) } if n.String() != tc.norm { t.Errorf("got %v; want %v", n.String(), tc.norm) } }) } } var diffOpts = []cmp.Option{ cmp.Comparer(func(x, y big.Rat) bool { return x.String() == y.String() }), cmp.Comparer(func(x, y big.Int) bool { return x.String() == y.String() }), cmp.AllowUnexported( NumInfo{}, ), cmpopts.IgnoreUnexported( token.Pos{}, ), cmpopts.EquateEmpty(), } func TestNumErrors(t *testing.T) { testCases := []string{ `0x`, `0o`, `0b`, `0_`, "0128", "e+100", ".p", ``, `"`, `"a`, `23.34e`, `23.34e33pp`, } for _, tc := range testCases { t.Run(fmt.Sprintf("%+q", tc), func(t *testing.T) { n := &NumInfo{} err := ParseNum(tc, n) if err == nil { t.Fatalf("expected error but found none") } }) } } cue-lang-cue-db9cc73/cue/literal/quote.go000066400000000000000000000170071474664451600204010ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "strconv" "strings" "unicode/utf8" ) // Form defines how to quote a string or bytes literal. type Form struct { hashCount int quote byte multiline bool auto bool exact bool asciiOnly bool graphicOnly bool indent string tripleQuote string } // TODO: // - Fixed or max level of escape modifiers (#""#). // - Option to fall back to bytes if value cannot be represented as string. // E.g. ExactString. // - QuoteExact that fails with an error if a string cannot be represented // without loss. // - Handle auto-breaking for long lines (Swift-style, \-terminated lines). // This is not supported yet in CUE, but may, and should be considered as // a possibility in API design. // - Other possible convenience forms: Blob (auto-break bytes), String (bytes // or string), Label. // WithTabIndent returns a new Form with indentation set to the given number // of tabs. The result will be a multiline string. func (f Form) WithTabIndent(n int) Form { f.indent = strings.Repeat("\t", n) f.multiline = true return f } // WithOptionalIndent is like WithTabIndent, but only returns a multiline // strings if it doesn't contain any newline characters. func (f Form) WithOptionalTabIndent(tabs int) Form { f.indent = strings.Repeat("\t", tabs) f.auto = true return f } // WithASCIIOnly ensures the quoted strings consists solely of valid ASCII // characters. func (f Form) WithASCIIOnly() Form { f.asciiOnly = true return f } // WithGraphicOnly ensures the quoted strings consists solely of printable // characters. func (f Form) WithGraphicOnly() Form { f.graphicOnly = true return f } var ( // String defines the format of a CUE string. Conversions may be lossy. String Form = stringForm // TODO: ExactString: quotes to bytes type if the string cannot be // represented without loss of accuracy. // Label is like String, but optimized for labels. Label Form = stringForm // Bytes defines the format of bytes literal. Bytes Form = bytesForm stringForm = Form{ quote: '"', tripleQuote: `"""`, } bytesForm = Form{ quote: '\'', tripleQuote: `'''`, exact: true, } ) // Quote returns CUE string literal representing s. The returned string uses CUE // escape sequences (\t, \n, \u00FF, \u0100) for control characters and // non-printable characters as defined by strconv.IsPrint. // // It reports an error if the string cannot be converted to the desired form. func (f Form) Quote(s string) string { return string(f.Append(make([]byte, 0, 3*len(s)/2), s)) } const ( lowerhex = "0123456789abcdef" ) // Append appends a CUE string literal representing s, as generated by Quote, to // buf and returns the extended buffer. func (f Form) Append(buf []byte, s string) []byte { if f.auto && strings.ContainsRune(s, '\n') { f.multiline = true } if f.multiline { f.hashCount = f.requiredHashCount(s) } // Often called with big strings, so preallocate. If there's quoting, // this is conservative but still helps a lot. if cap(buf)-len(buf) < len(s) { nBuf := make([]byte, len(buf), len(buf)+1+len(s)+1) copy(nBuf, buf) buf = nBuf } for range f.hashCount { buf = append(buf, '#') } if f.multiline { buf = append(buf, f.quote, f.quote, f.quote, '\n') if s == "" { buf = append(buf, f.indent...) buf = append(buf, f.quote, f.quote, f.quote) return buf } if len(s) > 0 && s[0] != '\n' { buf = append(buf, f.indent...) } } else { buf = append(buf, f.quote) } buf = f.appendEscaped(buf, s) if f.multiline { buf = append(buf, '\n') buf = append(buf, f.indent...) buf = append(buf, f.quote, f.quote, f.quote) } else { buf = append(buf, f.quote) } for range f.hashCount { buf = append(buf, '#') } return buf } // AppendEscaped appends a CUE string literal representing s, as generated by // Quote but without the quotes, to buf and returns the extended buffer. // // It does not include the last indentation. func (f Form) AppendEscaped(buf []byte, s string) []byte { if f.auto && strings.ContainsRune(s, '\n') { f.multiline = true } // Often called with big strings, so preallocate. If there's quoting, // this is conservative but still helps a lot. if cap(buf)-len(buf) < len(s) { nBuf := make([]byte, len(buf), len(buf)+1+len(s)+1) copy(nBuf, buf) buf = nBuf } buf = f.appendEscaped(buf, s) return buf } func (f Form) appendEscaped(buf []byte, s string) []byte { for width := 0; len(s) > 0; s = s[width:] { r := rune(s[0]) width = 1 if r >= utf8.RuneSelf { r, width = utf8.DecodeRuneInString(s) } if f.exact && width == 1 && r == utf8.RuneError { buf = append(buf, `\x`...) buf = append(buf, lowerhex[s[0]>>4]) buf = append(buf, lowerhex[s[0]&0xF]) continue } if f.multiline && r == '\n' { buf = append(buf, '\n') if len(s) > 1 && s[1] != '\n' { buf = append(buf, f.indent...) } continue } buf = f.appendEscapedRune(buf, r) } return buf } func (f *Form) appendEscapedRune(buf []byte, r rune) []byte { if (!f.multiline && r == rune(f.quote)) || r == '\\' { // always backslashed buf = f.appendEscape(buf) buf = append(buf, byte(r)) return buf } if f.asciiOnly { if r < utf8.RuneSelf && strconv.IsPrint(r) { buf = append(buf, byte(r)) return buf } } else if strconv.IsPrint(r) || (f.graphicOnly && strconv.IsGraphic(r)) { buf = utf8.AppendRune(buf, r) return buf } buf = f.appendEscape(buf) switch r { case '\a': buf = append(buf, 'a') case '\b': buf = append(buf, 'b') case '\f': buf = append(buf, 'f') case '\n': buf = append(buf, 'n') case '\r': buf = append(buf, 'r') case '\t': buf = append(buf, 't') case '\v': buf = append(buf, 'v') default: switch { case r < ' ' && f.exact: buf = append(buf, 'x') buf = append(buf, lowerhex[byte(r)>>4]) buf = append(buf, lowerhex[byte(r)&0xF]) case r > utf8.MaxRune: r = 0xFFFD fallthrough case r < 0x10000: buf = append(buf, 'u') for s := 12; s >= 0; s -= 4 { buf = append(buf, lowerhex[r>>uint(s)&0xF]) } default: buf = append(buf, 'U') for s := 28; s >= 0; s -= 4 { buf = append(buf, lowerhex[r>>uint(s)&0xF]) } } } return buf } func (f *Form) appendEscape(buf []byte) []byte { buf = append(buf, '\\') for range f.hashCount { buf = append(buf, '#') } return buf } // requiredHashCount returns the number of # characters // that are required to quote the multiline string s. func (f *Form) requiredHashCount(s string) int { hashCount := 0 i := 0 // Find all occurrences of the triple-quote and count // the maximum number of succeeding # characters. for { j := strings.Index(s[i:], f.tripleQuote) if j == -1 { break } i += j + 3 // Absorb all extra quotes, so we // get to the end of the sequence. for ; i < len(s); i++ { if s[i] != f.quote { break } } e := i - 1 // Count succeeding # characters. for ; i < len(s); i++ { if s[i] != '#' { break } } if nhash := i - e; nhash > hashCount { hashCount = nhash } } return hashCount } cue-lang-cue-db9cc73/cue/literal/quote_test.go000066400000000000000000000102721474664451600214350ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "fmt" "strings" "testing" "github.com/google/go-cmp/cmp" ) func TestQuote(t *testing.T) { testCases := []struct { form Form in string out string lossy bool }{ {form: String, in: "\x00", out: `"\u0000"`}, {form: String, in: "abc\xffdef", out: `"abc�def"`, lossy: true}, {form: Bytes, in: "abc\xffdef", out: `'abc\xffdef'`}, {form: String.WithASCIIOnly(), in: "abc\xffdef", out: `"abc\ufffddef"`, lossy: true}, {form: String, in: "\a\b\f\r\n\t\v", out: `"\a\b\f\r\n\t\v"`}, {form: String, in: "\"", out: `"\""`}, {form: String, in: "\\", out: `"\\"`}, {form: String, in: "\u263a", out: `"☺"`}, {form: String, in: "\U0010ffff", out: `"\U0010ffff"`}, {form: String, in: "\x04", out: `"\u0004"`}, {form: Bytes, in: "\x04", out: `'\x04'`}, {form: String.WithASCIIOnly(), in: "\u263a", out: `"\u263a"`}, {form: String.WithGraphicOnly(), in: "\u263a", out: `"☺"`}, { form: String.WithASCIIOnly(), in: "!\u00a0!\u2000!\u3000!", out: `"!\u00a0!\u2000!\u3000!"`, }, {form: String, in: "a\nb", out: `"a\nb"`}, {form: String.WithTabIndent(3), in: "a\nb", out: `""" a b """`}, {form: String.WithTabIndent(3), in: "a", out: `""" a """`}, {form: String.WithTabIndent(3), in: "a\n", out: `""" a """`}, {form: String.WithTabIndent(3), in: "", out: `""" """`}, {form: String.WithTabIndent(3), in: "\n", out: `""" """`}, {form: String.WithTabIndent(3), in: "\n\n", out: `""" """`}, {form: String.WithOptionalTabIndent(3), in: "a", out: `"a"`}, {form: String.WithOptionalTabIndent(3), in: "a\n", out: `""" a """`}, // Issue #541 {form: String.WithTabIndent(3), in: "foo\n\"bar\"", out: `""" foo "bar" """`}, {form: String.WithTabIndent(3), in: "foo\n\"\"\"bar\"", out: `#""" foo """bar" """#`}, {form: String.WithTabIndent(3), in: "foo\n\"\"\"\"\"###bar\"", out: `####""" foo """""###bar" """####`}, {form: String.WithTabIndent(3), in: "foo\n\"\"\"\r\f\\", out: `#""" foo """\#r\#f\#\ """#`}, {form: Bytes.WithTabIndent(3), in: "foo'''\nhello", out: `#''' foo''' hello '''#`}, {form: Bytes.WithTabIndent(3), in: "foo\n'''\r\f\\", out: `#''' foo '''\#r\#f\#\ '''#`}, } for _, tc := range testCases { t.Run(fmt.Sprintf("%q", tc.in), func(t *testing.T) { got := tc.form.Quote(tc.in) if got != tc.out { t.Errorf("Quote: %s", cmp.Diff(tc.out, got)) } got = string(tc.form.Append(nil, tc.in)) if got != tc.out { t.Errorf("Append: %s", cmp.Diff(tc.out, got)) } str, err := Unquote(got) if err != nil { t.Errorf("Roundtrip error: %v", err) } if !tc.lossy && str != tc.in { t.Errorf("Quote: %s", cmp.Diff(tc.in, str)) } }) } } func TestAppendEscaped(t *testing.T) { testCases := []struct { form Form in string out string }{ {String, "a", "a"}, {String, "", ""}, {String.WithTabIndent(2), "", ""}, {String.WithTabIndent(2), "\n", "\n"}, {String.WithTabIndent(2), "a\n", "a\n"}, {String.WithTabIndent(2), "a\nb", "a\n\t\tb"}, } for _, tc := range testCases { t.Run(tc.in, func(t *testing.T) { buf := tc.form.AppendEscaped(nil, tc.in) if got := string(buf); got != tc.out { t.Error(cmp.Diff(tc.out, got)) } }) } } func BenchmarkQuote(b *testing.B) { inputs := []string{ "aaaa", "aaaaaaa\n\naaaaaa", strings.Repeat("aaaaaaaaaaa\n", 1000), } for _, f := range []Form{ String, Bytes, String.WithTabIndent(3), String.WithOptionalTabIndent(3), } { b.Run("", func(b *testing.B) { for i := 0; i < b.N; i++ { for _, s := range inputs { f.Quote(s) } } }) } } cue-lang-cue-db9cc73/cue/literal/string.go000066400000000000000000000256741474664451600205630ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "errors" "strings" "unicode" "unicode/utf8" ) var ( errSyntax = errors.New("invalid syntax") errInvalidWhitespace = errors.New("invalid string: invalid whitespace") errMissingNewline = errors.New( "invalid string: opening quote of multiline string must be followed by newline") errUnmatchedQuote = errors.New("invalid string: unmatched quote") // TODO: making this an error is optional according to RFC 4627. But we // could make it not an error if this ever results in an issue. errSurrogate = errors.New("unmatched surrogate pair") errEscapedLastNewline = errors.New("last newline of multiline string cannot be escaped") ) // Unquote interprets s as a single- or double-quoted, single- or multi-line // string, possibly with custom escape delimiters, returning the string value // that s quotes. func Unquote(s string) (string, error) { info, nStart, _, err := ParseQuotes(s, s) if err != nil { return "", err } s = s[nStart:] return info.Unquote(s) } // QuoteInfo describes the type of quotes used for a string. type QuoteInfo struct { quote string whitespace string numHash int multiline bool char byte numChar byte } // IsDouble reports whether the literal uses double quotes. func (q QuoteInfo) IsDouble() bool { return q.char == '"' } // IsMulti reports whether a multi-line string was parsed. func (q QuoteInfo) IsMulti() bool { return q.multiline } // Whitespace returns prefix whitespace for multiline strings. func (q QuoteInfo) Whitespace() string { return q.whitespace } // ParseQuotes checks if the opening quotes in start matches the ending quotes // in end and reports its type as q or an error if they do not matching or are // invalid. nStart indicates the number of bytes used for the opening quote. func ParseQuotes(start, end string) (q QuoteInfo, nStart, nEnd int, err error) { for i, c := range start { if c != '#' { break } q.numHash = i + 1 } s := start[q.numHash:] switch s[0] { case '"', '\'': q.char = s[0] if len(s) > 3 && s[1] == s[0] && s[2] == s[0] { switch s[3] { case '\n': q.quote = start[:3+q.numHash] case '\r': if len(s) > 4 && s[4] == '\n' { q.quote = start[:4+q.numHash] break } fallthrough default: return q, 0, 0, errMissingNewline } q.multiline = true q.numChar = 3 nStart = len(q.quote) + 1 // add whitespace later } else { q.quote = start[:1+q.numHash] q.numChar = 1 nStart = len(q.quote) } default: return q, 0, 0, errSyntax } quote := start[:int(q.numChar)+q.numHash] for i := 0; i < len(quote); i++ { if j := len(end) - i - 1; j < 0 || quote[i] != end[j] { return q, 0, 0, errUnmatchedQuote } } if q.multiline { i := len(end) - len(quote) for i > 0 { r, size := utf8.DecodeLastRuneInString(end[:i]) if r == '\n' || !unicode.IsSpace(r) { break } i -= size } q.whitespace = end[i : len(end)-len(quote)] if len(start) > nStart && start[nStart] != '\n' { if !strings.HasPrefix(start[nStart:], q.whitespace) { return q, 0, 0, errInvalidWhitespace } nStart += len(q.whitespace) } } return q, nStart, int(q.numChar) + q.numHash, nil } // Unquote unquotes the given string, which should not contain // the initial quote character(s). It must be terminated with a quote or an // interpolation start. Escape sequences are expanded and surrogates // are replaced with the corresponding non-surrogate code points. func (q QuoteInfo) Unquote(s string) (string, error) { if len(s) > 0 && !q.multiline { if strings.ContainsAny(s, "\n\r") { return "", errSyntax } // Is it trivial? Avoid allocation. if s[len(s)-1] == q.char && q.numHash == 0 { if s := s[:len(s)-1]; isSimple(s, rune(q.char)) { return s, nil } } } buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. stripNL := false wasEscapedNewline := false for len(s) > 0 { switch s[0] { case '\r': s = s[1:] wasEscapedNewline = false continue case '\n': var err error s, err = skipWhitespaceAfterNewline(s[1:], q) if err != nil { return "", err } stripNL = true wasEscapedNewline = false buf = append(buf, '\n') continue } c, multibyte, ss, err := unquoteChar(s, q) if surHigh <= c && c < surEnd { if c >= surLow { return "", errSurrogate } var cl rune cl, _, ss, err = unquoteChar(ss, q) if cl < surLow || surEnd <= cl { return "", errSurrogate } c = 0x10000 + (c-surHigh)*0x400 + (cl - surLow) } if err != nil { return "", err } s = ss if c < 0 { switch c { case escapedNewline: var err error s, err = skipWhitespaceAfterNewline(s, q) if err != nil { return "", err } wasEscapedNewline = true continue case terminatedByQuote: if wasEscapedNewline { return "", errEscapedLastNewline } if stripNL { // Strip the last newline, but only if it came from a closing // quote. buf = buf[:len(buf)-1] } case terminatedByExpr: default: panic("unreachable") } return string(buf), nil } stripNL = false wasEscapedNewline = false if !multibyte { buf = append(buf, byte(c)) } else { buf = utf8.AppendRune(buf, c) } } // allow unmatched quotes if already checked. return "", errUnmatchedQuote } func skipWhitespaceAfterNewline(s string, q QuoteInfo) (string, error) { switch { case !q.multiline: // Can't happen because Unquote does an initial check for literal newlines // in the non-multiline case, but be defensive. fallthrough default: return "", errInvalidWhitespace case strings.HasPrefix(s, q.whitespace): s = s[len(q.whitespace):] case strings.HasPrefix(s, "\n"): case strings.HasPrefix(s, "\r\n"): } return s, nil } const ( surHigh = 0xD800 surLow = 0xDC00 surEnd = 0xE000 ) func isSimple(s string, quote rune) bool { // TODO(perf): check if using a simple DFA to detect surrogate pairs is // faster than converting to code points. At the very least there should // be an ASCII fast path. for _, r := range s { if r == quote || r == '\\' { return false } if surHigh <= r && r < surEnd { return false } } return true } const ( terminatedByQuote = rune(-1) terminatedByExpr = rune(-2) escapedNewline = rune(-3) ) // unquoteChar decodes the first character or byte in the escaped string. // It returns four values: // // 1. value, the decoded Unicode code point or byte value if non-negative, or // one of the following special values: // - terminatedByQuote indicates terminated by quotes // - terminatedByExpr means terminated by \( // - escapedNewline means that the line-termination character was quoted and should be omitted // 2. multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation; // 3. tail, the remainder of the string after the character; and // 4. an error that will be nil if the character is syntactically valid. // // The second argument, kind, specifies the type of literal being parsed // and therefore which kind of escape sequences are permitted. // For kind 's' only JSON escapes and \u{ are permitted. // For kind 'b' also hexadecimal and octal escape sequences are permitted. // // The third argument, quote, specifies that an ASCII quoting character that // is not permitted in the output. func unquoteChar(s string, info QuoteInfo) (value rune, multibyte bool, tail string, err error) { // easy cases switch c := s[0]; { case c == info.char && info.char != 0: for i := 1; byte(i) < info.numChar; i++ { if i >= len(s) || s[i] != info.char { return rune(info.char), false, s[1:], nil } } for i := 0; i < info.numHash; i++ { if i+int(info.numChar) >= len(s) || s[i+int(info.numChar)] != '#' { return rune(info.char), false, s[1:], nil } } if ln := int(info.numChar) + info.numHash; len(s) != ln { // TODO: terminating quote in middle of string return 0, false, s[ln:], errSyntax } return terminatedByQuote, false, "", nil case c >= utf8.RuneSelf: // TODO: consider handling surrogate values. These are discarded by // DecodeRuneInString. It is technically correct to disallow it, but // some JSON parsers allow this anyway. r, size := utf8.DecodeRuneInString(s) return r, true, s[size:], nil case c != '\\': return rune(s[0]), false, s[1:], nil } if len(s) <= 1+info.numHash { return '\\', false, s[1:], nil } for i := 1; i <= info.numHash && i < len(s); i++ { if s[i] != '#' { return '\\', false, s[1:], nil } } c := s[1+info.numHash] s = s[2+info.numHash:] switch c { case 'a': value = '\a' case 'b': value = '\b' case 'f': value = '\f' case 'n': value = '\n' case 'r': value = '\r' case 't': value = '\t' case 'v': value = '\v' case '/': value = '/' case 'x', 'u', 'U': n := 0 switch c { case 'x': n = 2 case 'u': n = 4 case 'U': n = 8 } var v rune if len(s) < n { err = errSyntax return } for j := 0; j < n; j++ { x, ok := unhex(s[j]) if !ok { err = errSyntax return } v = v<<4 | x } s = s[n:] if c == 'x' { if info.char == '"' { err = errSyntax return } // single-byte string, possibly not UTF-8 value = v break } if v > utf8.MaxRune { err = errSyntax return } value = v multibyte = true case '0', '1', '2', '3', '4', '5', '6', '7': if info.char == '"' { err = errSyntax return } v := rune(c) - '0' if len(s) < 2 { err = errSyntax return } for j := 0; j < 2; j++ { // one digit already; two more x := rune(s[j]) - '0' if x < 0 || x > 7 { err = errSyntax return } v = (v << 3) | x } s = s[2:] if v > 255 { err = errSyntax return } value = v case '\\': value = '\\' case '\'', '"': // TODO: should we allow escaping of quotes regardless? if c != info.char { err = errSyntax return } value = rune(c) case '(': if s != "" { // TODO: terminating quote in middle of string return 0, false, s, errSyntax } value = terminatedByExpr case '\r': if len(s) == 0 || s[0] != '\n' { err = errSyntax return } s = s[1:] value = escapedNewline case '\n': value = escapedNewline default: err = errSyntax return } tail = s return } func unhex(b byte) (v rune, ok bool) { c := rune(b) switch { case '0' <= c && c <= '9': return c - '0', true case 'a' <= c && c <= 'f': return c - 'a' + 10, true case 'A' <= c && c <= 'F': return c - 'A' + 10, true } return } cue-lang-cue-db9cc73/cue/literal/string_test.go000066400000000000000000000135741474664451600216160ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package literal import ( "fmt" "testing" ) func TestUnquote(t *testing.T) { testCases := []struct { in, out string err error }{ {`"Hello"`, "Hello", nil}, {`'Hello'`, "Hello", nil}, {`'Hellø'`, "Hellø", nil}, {`"""` + "\n\t\tHello\n\t\t" + `"""`, "Hello", nil}, {`"""` + "\r\n\tHello\r\n\n\t" + `"""`, "Hello\n", nil}, {"'''\n\t\tHello\n\t\t'''", "Hello", nil}, {`"""` + "\n\tHello \\\n\tworld\n\t" + `"""`, "Hello world", nil}, {`"""` + "\r\n\tHello \\\r\n\tworld\r\n\t" + `"""`, "Hello world", nil}, {`"""` + "\none \\\ntwo \\\nthree\n" + `"""`, "one two three", nil}, {`"""` + "\nHello\\\n" + `"""`, "", errEscapedLastNewline}, {`"""` + "\n\tHello\\\n\t" + `"""`, "", errEscapedLastNewline}, {`"""` + "\r\n\tHello\\\r\n\t" + `"""`, "", errEscapedLastNewline}, {"'''\n\t\tHello\n\n\t\t'''", "Hello\n", nil}, {"'''\n\n\t\tHello\n\t\t'''", "\nHello", nil}, {"'''\n\n\n\n\t\t'''", "\n\n", nil}, {"'''\n\t\t'''", "", nil}, {`"""` + "\n\raaa\n\rbbb\n\r" + `"""`, "aaa\nbbb", nil}, {`'\a\b\f\n\r\t\v\'\\\/'`, "\a\b\f\n\r\t\v'\\/", nil}, {`"\a\b\f\n\r\t\v\"\\\/"`, "\a\b\f\n\r\t\v\"\\/", nil}, {`#"The sequence "\U0001F604" renders as \#U0001F604."#`, `The sequence "\U0001F604" renders as 😄.`, nil}, {`" \U00010FfF"`, " \U00010fff", nil}, {`"\u0061 "`, "a ", nil}, {`'\x61\x55'`, "\x61\x55", nil}, {`'\061\055'`, "\061\055", nil}, {`'\377 '`, "\377 ", nil}, {"'e\u0300\\n'", "e\u0300\n", nil}, {`'\06\055'`, "", errSyntax}, {`'\0'`, "", errSyntax}, {`"\06\055"`, "", errSyntax}, // too short {`'\777 '`, "", errSyntax}, // overflow {`'\U012301'`, "", errSyntax}, // too short {`'\U0123012G'`, "", errSyntax}, // invalid digit G {`"\x04"`, "", errSyntax}, // not allowed in strings {`'\U01230123'`, "", errSyntax}, // too large // Surrogate pairs {`"\uD834\uDD1E"`, "𝄞", nil}, {`"\uDD1E\uD834"`, "", errSurrogate}, {`"\uD834\uD834"`, "", errSurrogate}, {`"\\"`, "\\", nil}, {`"\'"`, "", errSyntax}, {`"\q"`, "", errSyntax}, {"'\n'", "", errSyntax}, {"'---\n---'", "", errSyntax}, {"'''\r'''", "", errMissingNewline}, {`#"Hello"#`, "Hello", nil}, {`#"Hello\v"#`, "Hello\\v", nil}, {`#"Hello\#v\r"#`, "Hello\v\\r", nil}, {`##"Hello\##v\r"##`, "Hello\v\\r", nil}, {`##"Hello\##v"##`, "Hello\v", nil}, {"#'''\n\t\tHello\\#v\n\t\t'''#", "Hello\v", nil}, {"##'''\n\t\tHello\\#v\n\t\t'''##", "Hello\\#v", nil}, {`#"""` + "\n\t\t\\#r\n\t\t" + `"""#`, "\r", nil}, {`#""#`, "", nil}, {`#" ""#`, ` "`, nil}, {`#" """#`, ` ""`, nil}, {`##" """# "##`, ` """# `, nil}, {`##" """# "##`, ` """# `, nil}, {`#"This is a "dog""#`, `This is a "dog"`, nil}, {"#\"\"\"\n\"\n\"\"\"#", `"`, nil}, {"#\"\"\"\n\"\"\"\n\"\"\"#", `"""`, nil}, {"#\"\"\"\n\na\n\n\"\"\"#", "\na\n", nil}, // Gobble extra \r {"#\"\"\"\n\ra\n\r\"\"\"#", `a`, nil}, {"#\"\"\"\n\r\n\ra\n\r\n\r\"\"\"#", "\na\n", nil}, // Make sure this works for Windows. {"#\"\"\"\r\n\r\na\r\n\r\n\"\"\"#", "\na\n", nil}, {"#\"\"\"\r\n \r\n a\r\n \r\n \"\"\"#", "\na\n", nil}, {"#\"\"\"\r\na\r\n\"\"\"#", `a`, nil}, {"#\"\"\"\r\n\ra\r\n\r\"\"\"#", `a`, nil}, {`####" \"####`, ` \`, nil}, {"```", "", errSyntax}, {"Hello", "", errSyntax}, {`"Hello`, "", errUnmatchedQuote}, {`"""Hello"""`, "", errMissingNewline}, {"'''\n Hello\n '''", "", errInvalidWhitespace}, {"'''\n a\n b\n '''", "", errInvalidWhitespace}, {`"Hello""`, "", errSyntax}, {`#"Hello"`, "", errUnmatchedQuote}, {`#"Hello'#`, "", errUnmatchedQuote}, {`#""" """#`, "", errMissingNewline}, {`"""` + "\r\n\tHello \\\r", "", errUnmatchedQuote}, // TODO: should this be legal? {`#"""#`, "", errMissingNewline}, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d/%s", i, tc.in), func(t *testing.T) { if got, err := Unquote(tc.in); err != tc.err { t.Errorf("error: got %#v; want %#v", err, tc.err) } else if got != tc.out { t.Errorf("value: got %q; want %q", got, tc.out) } }) } } func TestInterpolation(t *testing.T) { testCases := []struct { quotes string in string out string err error }{ {`""`, `foo\(`, "foo", nil}, {`"""` + "\n" + `"""`, `foo`, "", errUnmatchedQuote}, {`#""#`, `foo\#(`, "foo", nil}, {`#""#`, `foo\(`, "", errUnmatchedQuote}, {`""`, `foo\(bar`, "", errSyntax}, {`""`, ``, "", errUnmatchedQuote}, {`#""#`, `"`, "", errUnmatchedQuote}, {`#""#`, `\`, "", errUnmatchedQuote}, {`##""##`, `\'`, "", errUnmatchedQuote}, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d/%s/%s", i, tc.quotes, tc.in), func(t *testing.T) { info, _, _, _ := ParseQuotes(tc.quotes, tc.quotes) if got, err := info.Unquote(tc.in); err != tc.err { t.Errorf("error: got %q; want %q", err, tc.err) } else if got != tc.out { t.Errorf("value: got %q; want %q", got, tc.out) } }) } } func TestIsDouble(t *testing.T) { testCases := []struct { quotes string double bool }{ {`""`, true}, {`"""` + "\n" + `"""`, true}, {`#""#`, true}, {`''`, false}, {`'''` + "\n" + `'''`, false}, {`#''#`, false}, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d/%s", i, tc.quotes), func(t *testing.T) { info, _, _, err := ParseQuotes(tc.quotes, tc.quotes) if err != nil { t.Fatal(err) } if got := info.IsDouble(); got != tc.double { t.Errorf("got %v; want %v", got, tc.double) } }) } } cue-lang-cue-db9cc73/cue/load/000077500000000000000000000000001474664451600161735ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/config.go000066400000000000000000000403521474664451600177730ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "context" "fmt" "io" "os" "path/filepath" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/mod/modconfig" "cuelang.org/go/mod/modfile" "cuelang.org/go/mod/module" ) const ( cueSuffix = ".cue" modDir = "cue.mod" moduleFile = "module.cue" ) // FromArgsUsage is a partial usage message that applications calling // FromArgs may wish to include in their -help output. // // Some of the aspects of this documentation, like flags and handling '--' need // to be implemented by the tools. const FromArgsUsage = ` is a list of arguments denoting a set of instances of the form: * * 1. A list of source files CUE files are parsed, loaded and unified into a single instance. All files must have the same package name. Data files, like YAML or JSON, are handled in one of two ways: a. Explicitly mapped into a single CUE namespace, using the --path, --files and --list flags. In this case these are unified into a single instance along with any other CUE files. b. Treated as a stream of data elements that each is optionally unified with a single instance, which either consists of the other CUE files specified on the command line or a single package. By default, the format of files is derived from the file extension. This behavior may be modified with file arguments of the form : For instance, cue eval foo.cue json: bar.data indicates that the bar.data file should be interpreted as a JSON file. A qualifier applies to all files following it until the next qualifier. The following qualifiers are available: encodings cue CUE definitions and data json JSON data, one value only jsonl newline-separated JSON values yaml a YAML file, may contain a stream proto Protobuf definitions interpretations jsonschema data encoding describes JSON Schema openapi data encoding describes Open API formats data output as -- or only accept -- data graph data allowing references or anchors schema output as schema; defaults JSON files to JSON Schema def full definitions, including documentation 2. A list of relative directories to denote a package instance. Each directory matching the pattern is loaded as a separate instance. The instance contains all files in this directory and ancestor directories, up to the module root, with the same package name. The package name must be either uniquely determined by the files in the given directory, or explicitly defined using a package name qualifier. For instance, ./...:foo selects all packages named foo in the any subdirectory of the current working directory. 3. An import path referring to a directory within the current module All CUE files in that directory, and all the ancestor directories up to the module root (if applicable), with a package name corresponding to the base name of the directory or the optional explicit package name are loaded into a single instance. Examples, assume a module name of acme.org/root: mod.test/foo package in cue.mod ./foo package corresponding to foo directory .:bar package in current directory with package name bar ` // GenPath reports the directory in which to store generated // files. func GenPath(root string) string { return internal.GenPath(root) } // A Config configures load behavior. type Config struct { // TODO: allow passing a cuecontext to be able to lookup and verify builtin // packages at loading time. // Context specifies the context for the load operation. Context *build.Context // ModuleRoot is the directory that contains the cue.mod directory // as well as all the packages which form part of the module being loaded. // // If left as the empty string, a module root is found by walking parent directories // starting from [Config.Dir] until one is found containing a cue.mod directory. // If it is a relative path, it will be interpreted relative to [Config.Dir]. ModuleRoot string // Module specifies the module prefix. If not empty, this value must match // the module field of an existing cue.mod file. Module string // AcceptLegacyModules causes the module resolution code // to accept module files that lack a language.version field. AcceptLegacyModules bool // modFile holds the contents of the module file, or nil // if no module file was present. If non-nil, then // after calling Config.complete, modFile.Module will be // equal to Module. modFile *modfile.File // Package defines the name of the package to be loaded. If this is not set, // the package must be uniquely defined from its context. Special values: // _ load files without a package // * load all packages. Files without packages are loaded // in the _ package. Package string // Dir is the base directory for import path resolution. // For example, it is used to determine the main module, // and rooted import paths starting with "./" are relative to it. // If Dir is empty, the current directory is used. Dir string // Tags defines boolean tags or key-value pairs to select files to build // or be injected as values in fields. // // Each string is of the form // // key [ "=" value ] // // where key is a valid CUE identifier and value valid CUE scalar. // // The Tags values are used to both select which files get included in a // build and to inject values into the AST. // // // File selection // // Files with an attribute of the form @if(expr) before a package clause // are conditionally included if expr resolves to true, where expr refers to // boolean values in Tags. // // It is an error for a file to have more than one @if attribute or to // have a @if attribute without or after a package clause. // // // Value injection // // The Tags values are also used to inject values into fields with a // @tag attribute. // // For any field of the form // // field: x @tag(key) // // and Tags value for which the name matches key, the field will be // modified to // // field: x & "value" // // By default, the injected value is treated as a string. Alternatively, a // "type" option of the @tag attribute allows a value to be interpreted as // an int, number, or bool. For instance, for a field // // field: x @tag(key,type=int) // // an entry "key=2" modifies the field to // // field: x & 2 // // Valid values for type are "int", "number", "bool", and "string". // // A @tag attribute can also define shorthand values, which can be injected // into the fields without having to specify the key. For instance, for // // environment: string @tag(env,short=prod|staging) // // the Tags entry "prod" sets the environment field to the value "prod". // This is equivalent to a Tags entry of "env=prod". // // The use of @tag does not preclude using any of the usual CUE constraints // to limit the possible values of a field. For instance // // environment: "prod" | "staging" @tag(env,short=prod|staging) // // ensures the user may only specify "prod" or "staging". Tags []string // TagVars defines a set of key value pair the values of which may be // referenced by tags. // // Use DefaultTagVars to get a pre-loaded map with supported values. TagVars map[string]TagVar // Include all files, regardless of tags. AllCUEFiles bool // If Tests is set, the loader includes not just the packages // matching a particular pattern but also any related test packages. Tests bool // If Tools is set, the loader includes tool files associated with // a package. Tools bool // SkipImports causes the loading to ignore all imports and dependencies. // The registry will never be consulted. Any external package paths // mentioned on the command line will result in an error. // The [cue/build.Instance.Imports] field will be empty. SkipImports bool // If DataFiles is set, the loader includes entries for directories that // have no CUE files, but have recognized data files that could be converted // to CUE. DataFiles bool // ParseFile is called to read and parse each file when preparing a // package's syntax tree. It must be safe to call ParseFile simultaneously // from multiple goroutines. If ParseFile is nil, the loader will uses // parser.ParseFile. // // ParseFile should parse the source from src and use filename only for // recording position information. // // An application may supply a custom implementation of ParseFile to change // the effective file contents or the behavior of the parser, or to modify // the syntax tree. ParseFile func(name string, src interface{}) (*ast.File, error) // Overlay provides a mapping of absolute file paths to file contents. If // the file with the given path already exists, the parser will use the // alternative file contents provided by the map. Overlay map[string]Source // Stdin defines an alternative for os.Stdin for the file "-". When used, // the corresponding build.File will be associated with the full buffer. Stdin io.Reader // Registry is used to fetch CUE module dependencies. // // When nil, [modconfig.NewRegistry] will be used to create a // registry instance using the variables set in [Config.Env] // as documented in `[cue help registryconfig]`. // // THIS IS EXPERIMENTAL. API MIGHT CHANGE. // // [cue help registryconfig]: https://cuelang.org/docs/reference/command/cue-help-registryconfig/ Registry modconfig.Registry // Env provides environment variables for use in the configuration. // Currently this is only used in the construction of the Registry // value (see above). If this is nil, the current process's environment // will be used. Env []string fileSystem *fileSystem } func (c *Config) stdin() io.Reader { if c.Stdin == nil { return os.Stdin } return c.Stdin } type importPath string func addImportQualifier(pkg importPath, name string) (importPath, error) { if name == "" { return pkg, nil } ip := module.ParseImportPath(string(pkg)) if ip.Qualifier == "_" { return "", fmt.Errorf("invalid import qualifier _ in %q", pkg) } if ip.ExplicitQualifier && ip.Qualifier != name { return "", fmt.Errorf("non-matching package names (%s != %s)", ip.Qualifier, name) } ip.Qualifier = name return importPath(ip.String()), nil } // Complete updates the configuration information. After calling complete, // the following invariants hold: // - c.Dir is an absolute path. // - c.ModuleRoot is an absolute path // - c.Module is set to the module import prefix if there is a cue.mod file // with the module property. // - c.loader != nil // - c.cache != "" // // It does not initialize c.Context, because that requires the // loader in order to use for build.Loader. func (c Config) complete() (cfg *Config, err error) { if c.Dir == "" { c.Dir, err = os.Getwd() if err != nil { return nil, err } } else if c.Dir, err = filepath.Abs(c.Dir); err != nil { return nil, err } // TODO: we could populate this already with absolute file paths, // but relative paths cannot be added. Consider what is reasonable. fsys, err := newFileSystem(&c) if err != nil { return nil, err } c.fileSystem = fsys // TODO: determine root on a package basis. Maybe we even need a // pkgname.cue.mod // Look to see if there is a cue.mod. // // TODO(mvdan): note that setting Config.ModuleRoot to a directory // without a cue.mod file does not result in any error, which is confusing // or can lead to not using the right CUE module silently. if c.ModuleRoot == "" { // Only consider the current directory by default c.ModuleRoot = c.Dir if root := c.findModRoot(c.Dir); root != "" { c.ModuleRoot = root } } else if !filepath.IsAbs(c.ModuleRoot) { c.ModuleRoot = filepath.Join(c.Dir, c.ModuleRoot) } if c.SkipImports { // We should never use the registry in SkipImports mode // but nil it out to be sure. c.Registry = nil } else if c.Registry == nil { registry, err := modconfig.NewRegistry(&modconfig.Config{ Env: c.Env, }) if err != nil { // If there's an error in the registry configuration, // don't error immediately, but only when we actually // need to resolve modules. registry = errorRegistry{err} } c.Registry = registry } if err := c.loadModule(); err != nil { return nil, err } return &c, nil } // loadModule loads the module file, resolves and downloads module // dependencies. It sets c.Module if it's empty or checks it for // consistency with the module file otherwise. // // Note that this function is a no-op if a module file does not exist, // as it is still possible to load CUE without a module. func (c *Config) loadModule() error { // TODO: also make this work if run from outside the module? modDir := filepath.Join(c.ModuleRoot, modDir) modFile := filepath.Join(modDir, moduleFile) f, cerr := c.fileSystem.openFile(modFile) if cerr != nil { // If we could not load cue.mod/module.cue, check whether the reason was // a legacy cue.mod file and give the user a clear error message. info, cerr2 := c.fileSystem.stat(modDir) if cerr2 == nil && !info.IsDir() { return fmt.Errorf("cue.mod files are no longer supported; use cue.mod/module.cue") } return nil } defer f.Close() data, err := io.ReadAll(f) if err != nil { return err } parseModFile := modfile.ParseNonStrict if c.Registry == nil { parseModFile = modfile.ParseLegacy } else if c.AcceptLegacyModules { // Note: technically this does not support all legacy module // files because some old module files might contain non-concrete // data, but that seems like an OK restriction for now at least, // given that no actual instances of non-concrete data in // module files have been discovered in the wild. parseModFile = modfile.FixLegacy } mf, err := parseModFile(data, modFile) if err != nil { return err } c.modFile = mf if mf.QualifiedModule() == "" { // Backward compatibility: allow empty module.cue file. // TODO maybe check that the rest of the fields are empty too? return nil } if c.Module != "" && c.Module != mf.Module { return errors.Newf(token.NoPos, "inconsistent modules: got %q, want %q", mf.Module, c.Module) } c.Module = mf.QualifiedModule() return nil } func (c Config) isModRoot(dir string) bool { // Note: cue.mod used to be a file. We still allow both to match. _, err := c.fileSystem.stat(filepath.Join(dir, modDir)) return err == nil } // findModRoot returns the module root that's ancestor // of the given absolute directory path, or "" if none was found. func (c Config) findModRoot(absDir string) string { abs := absDir for { if c.isModRoot(abs) { return abs } d := filepath.Dir(abs) if filepath.Base(filepath.Dir(abs)) == modDir { // The package was located within a "cue.mod" dir and there was // not cue.mod found until now. So there is no root. return "" } if len(d) >= len(abs) { return "" // reached top of file system, no cue.mod } abs = d } } func (c *Config) newErrInstance(err error) *build.Instance { i := c.Context.NewInstance("", nil) i.Root = c.ModuleRoot i.Module = c.Module i.Err = errors.Promote(err, "") return i } // errorRegistry implements [modconfig.Registry] by returning err from all methods. type errorRegistry struct { err error } func (r errorRegistry) Requirements(ctx context.Context, m module.Version) ([]module.Version, error) { return nil, r.err } func (r errorRegistry) Fetch(ctx context.Context, m module.Version) (module.SourceLoc, error) { return module.SourceLoc{}, r.err } func (r errorRegistry) ModuleVersions(ctx context.Context, mpath string) ([]string, error) { return nil, r.err } cue-lang-cue-db9cc73/cue/load/doc.go000066400000000000000000000016621474664451600172740ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package load loads CUE instances. package load // Trigger the unconditional loading of all core builtin packages if load is used. // This was deemed the simplest way to avoid having to import this line explicitly, // and thus breaking existing code, for the majority of cases, // while not introducing an import cycle. import _ "cuelang.org/go/pkg" cue-lang-cue-db9cc73/cue/load/errors.go000066400000000000000000000111631474664451600200400ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "fmt" "path/filepath" "strings" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" ) // A PackageError describes an error loading information about a package. type PackageError struct { ImportStack []string // shortest path from package named on command line to this one Pos token.Pos // position of error errors.Message // the error itself IsImportCycle bool // the error is an import cycle } func (p *PackageError) Position() token.Pos { return p.Pos } func (p *PackageError) InputPositions() []token.Pos { return nil } func (p *PackageError) Path() []string { return p.ImportStack } func (p *PackageError) fillPos(cwd string, positions []token.Pos) { if len(positions) > 0 && !p.Pos.IsValid() { p.Pos = positions[0] } } // TODO(localize) func (p *PackageError) Error() string { // Import cycles deserve special treatment. if p.IsImportCycle { return fmt.Sprintf("%s\npackage %s\n", p.Message, strings.Join(p.ImportStack, "\n\timports ")) } if p.Pos.IsValid() { // Omit import stack. The full path to the file where the error // is the most important thing. return p.Pos.String() + ": " + p.Message.Error() } if len(p.ImportStack) == 0 { return p.Message.Error() } return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Message.Error() } // NoFilesError is the error used by Import to describe a directory // containing no usable source files. (It may still contain // tool files, files hidden by build tags, and so on.) type NoFilesError struct { Package *build.Instance ignored bool // whether any CUE files were ignored due to build tags } func (e *NoFilesError) Position() token.Pos { return token.NoPos } func (e *NoFilesError) InputPositions() []token.Pos { return nil } func (e *NoFilesError) Path() []string { return nil } // TODO(localize) func (e *NoFilesError) Msg() (string, []interface{}) { return e.Error(), nil } // TODO(localize) func (e *NoFilesError) Error() string { // Count files beginning with _, which we will pretend don't exist at all. dummy := 0 for _, f := range e.Package.IgnoredFiles { if strings.HasPrefix(filepath.Base(f.Filename), "_") { dummy++ } } // path := shortPath(e.Package.Root, e.Package.Dir) path := e.Package.DisplayPath if len(e.Package.IgnoredFiles) > dummy { b := strings.Builder{} b.WriteString("build constraints exclude all CUE files in ") b.WriteString(path) b.WriteString(":") // CUE files exist, but they were ignored due to build constraints. for _, f := range e.Package.IgnoredFiles { b.WriteString("\n ") b.WriteString(filepath.ToSlash(e.Package.RelPath(f))) if f.ExcludeReason != nil { b.WriteString(": ") b.WriteString(f.ExcludeReason.Error()) } } return b.String() } // if len(e.Package.TestCUEFiles) > 0 { // // Test CUE files exist, but we're not interested in them. // // The double-negative is unfortunate but we want e.Package.Dir // // to appear at the end of error message. // return "no non-test CUE files in " + e.Package.Dir // } return "no CUE files in " + path } // MultiplePackageError describes an attempt to build a package composed of // CUE files from different packages. type MultiplePackageError struct { Dir string // directory containing files Packages []string // package names found Files []string // corresponding files: Files[i] declares package Packages[i] } func (e *MultiplePackageError) Position() token.Pos { return token.NoPos } func (e *MultiplePackageError) InputPositions() []token.Pos { return nil } func (e *MultiplePackageError) Path() []string { return nil } func (e *MultiplePackageError) Msg() (string, []interface{}) { return "found packages %q (%s) and %q (%s) in %q", []interface{}{ e.Packages[0], e.Files[0], e.Packages[1], e.Files[1], e.Dir, } } func (e *MultiplePackageError) Error() string { // Error string limited to two entries for compatibility. format, args := e.Msg() return fmt.Sprintf(format, args...) } cue-lang-cue-db9cc73/cue/load/example_test.go000066400000000000000000000103301474664451600212110ustar00rootroot00000000000000// Copyright 2023 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load_test import ( "fmt" "os" "path/filepath" "golang.org/x/tools/txtar" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/load" "cuelang.org/go/internal/registrytest" ) // Note that these examples may not be runnable on pkg.go.dev, // as they expect files to be present inside testdata. // Using cue/load with real files on disk keeps the example realistic // and enables the user to easily tweak the code to their needs. func Example() { // Load the package "example" relative to the directory testdata/testmod. // Akin to loading via: cd testdata/testmod && cue export ./example insts := load.Instances([]string{"./example"}, &load.Config{ Dir: filepath.Join("testdata", "testmod"), Env: []string{}, // or nil to use os.Environ }) // testdata/testmod/example just has one file without any build tags, // so we get a single instance as a result. fmt.Println("Number of instances:", len(insts)) inst := insts[0] if err := inst.Err; err != nil { fmt.Println(err) return } fmt.Println("Instance module:", inst.Module) fmt.Println("Instance import path:", inst.ImportPath) fmt.Println() // Inspect the syntax trees. fmt.Println("Source files:") for _, file := range inst.Files { fmt.Println(filepath.Base(file.Filename), "with", len(file.Decls), "declarations") } fmt.Println() // Build the instance into a value. // We can also use BuildInstances for many instances at once. ctx := cuecontext.New() val := ctx.BuildInstance(inst) if err := val.Err(); err != nil { fmt.Println(err) return } // Inspect the contents of the value, such as one string field. fieldStr, err := val.LookupPath(cue.MakePath(cue.Str("output"))).String() if err != nil { fmt.Println(err) return } fmt.Println("Field string:", fieldStr) // Output: // Number of instances: 1 // Instance module: mod.test/test@v0 // Instance import path: mod.test/test/example@v0 // // Source files: // example.cue with 3 declarations // // Field string: Hello Joe } func Example_externalModules() { // setUpModulesExample starts a temporary in-memory registry, // populates it with an example module, and sets CUE_REGISTRY to refer to it. // Users can leave [load.Config.Env] empty to use the default registry, // or set one globally with os.Setenv("CUE_REGISTRY", "registry.myorg.com"). env, cleanup := setUpModulesExample() defer cleanup() insts := load.Instances([]string{"."}, &load.Config{ Dir: filepath.Join("testdata", "testmod-external"), Env: env, // or nil to use os.Environ }) inst := insts[0] if err := inst.Err; err != nil { fmt.Println(err) return } ctx := cuecontext.New() val := ctx.BuildInstance(inst) if err := val.Err(); err != nil { fmt.Println(err) return } // Inspect the contents of the value, such as one string field. fieldStr, err := val.LookupPath(cue.MakePath(cue.Str("output"))).String() if err != nil { fmt.Println(err) return } fmt.Println("Field string:", fieldStr) // Output: // Field string: hello, world } func setUpModulesExample() (env []string, cleanup func()) { registryFS, err := txtar.FS(txtar.Parse([]byte(` -- foo.example_v0.0.1/cue.mod/module.cue -- module: "foo.example@v0" language: version: "v0.8.0" -- foo.example_v0.0.1/bar/bar.cue -- package bar value: "world" `))) if err != nil { panic(err) } registry, err := registrytest.New(registryFS, "") if err != nil { panic(err) } env = append(env, "CUE_REGISTRY="+registry.Host()+"+insecure") // We also set up a temporary cache directory to fetch and extract modules into. dir, err := os.MkdirTemp("", "") if err != nil { panic(err) } env = append(env, "CUE_CACHE_DIR="+dir) return env, registry.Close } cue-lang-cue-db9cc73/cue/load/fs.go000066400000000000000000000273301474664451600171370ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "bytes" "cmp" "fmt" "io" iofs "io/fs" "os" "path/filepath" "slices" "strings" "sync" "time" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/encoding" "cuelang.org/go/mod/module" ) type overlayFile struct { basename string contents []byte file *ast.File modtime time.Time isDir bool } func (f *overlayFile) Name() string { return f.basename } func (f *overlayFile) Size() int64 { return int64(len(f.contents)) } func (f *overlayFile) Mode() iofs.FileMode { if f.isDir { return iofs.ModeDir | 0o555 } return 0o444 } func (f *overlayFile) ModTime() time.Time { return f.modtime } func (f *overlayFile) IsDir() bool { return f.isDir } func (f *overlayFile) Sys() interface{} { return nil } // A fileSystem specifies the supporting context for a build. type fileSystem struct { overlayDirs map[string]map[string]*overlayFile cwd string fileCache *fileCache } func (fs *fileSystem) getDir(dir string, create bool) map[string]*overlayFile { dir = filepath.Clean(dir) m, ok := fs.overlayDirs[dir] if !ok && create { m = map[string]*overlayFile{} fs.overlayDirs[dir] = m } return m } // ioFS returns an implementation of [io/fs.FS] that holds // the contents of fs under the given filepath root. // // Note: we can't return an FS implementation that covers the // entirety of fs because the overlay paths may not all share // a common root. // // Note also: the returned FS also implements // [modpkgload.OSRootFS] so that we can map // the resulting source locations back to the filesystem // paths required by most of the `cue/load` package // implementation. func (fs *fileSystem) ioFS(root string) iofs.FS { return &ioFS{ fs: fs, root: root, } } func newFileSystem(cfg *Config) (*fileSystem, error) { fs := &fileSystem{ cwd: cfg.Dir, overlayDirs: map[string]map[string]*overlayFile{}, } // Organize overlay for filename, src := range cfg.Overlay { if !filepath.IsAbs(filename) { return nil, fmt.Errorf("non-absolute file path %q in overlay", filename) } // TODO: do we need to further clean the path or check that the // specified files are within the root/ absolute files? dir, base := filepath.Split(filename) m := fs.getDir(dir, true) b, file, err := src.contents() if err != nil { return nil, err } m[base] = &overlayFile{ basename: base, contents: b, file: file, modtime: time.Now(), } for { prevdir := dir dir, base = filepath.Split(filepath.Dir(dir)) if dir == prevdir || dir == "" { break } m := fs.getDir(dir, true) if m[base] == nil { m[base] = &overlayFile{ basename: base, modtime: time.Now(), isDir: true, } } } } fs.fileCache = newFileCache(cfg) return fs, nil } func (fs *fileSystem) makeAbs(path string) string { if filepath.IsAbs(path) { return path } return filepath.Join(fs.cwd, path) } func (fs *fileSystem) readDir(path string) ([]iofs.DirEntry, errors.Error) { path = fs.makeAbs(path) m := fs.getDir(path, false) items, err := os.ReadDir(path) if err != nil { if !os.IsNotExist(err) || m == nil { return nil, errors.Wrapf(err, token.NoPos, "readDir") } } if m == nil { return items, nil } done := map[string]bool{} for i, fi := range items { done[fi.Name()] = true if o := m[fi.Name()]; o != nil { items[i] = iofs.FileInfoToDirEntry(o) } } for _, o := range m { if !done[o.Name()] { items = append(items, iofs.FileInfoToDirEntry(o)) } } slices.SortFunc(items, func(a, b iofs.DirEntry) int { return cmp.Compare(a.Name(), b.Name()) }) return items, nil } func (fs *fileSystem) getOverlay(path string) *overlayFile { dir, base := filepath.Split(path) if m := fs.getDir(dir, false); m != nil { return m[base] } return nil } func (fs *fileSystem) stat(path string) (iofs.FileInfo, errors.Error) { path = fs.makeAbs(path) if fi := fs.getOverlay(path); fi != nil { return fi, nil } fi, err := os.Stat(path) if err != nil { return nil, errors.Wrapf(err, token.NoPos, "stat") } return fi, nil } func (fs *fileSystem) lstat(path string) (iofs.FileInfo, errors.Error) { path = fs.makeAbs(path) if fi := fs.getOverlay(path); fi != nil { return fi, nil } fi, err := os.Lstat(path) if err != nil { return nil, errors.Wrapf(err, token.NoPos, "stat") } return fi, nil } func (fs *fileSystem) openFile(path string) (io.ReadCloser, errors.Error) { path = fs.makeAbs(path) if fi := fs.getOverlay(path); fi != nil { return io.NopCloser(bytes.NewReader(fi.contents)), nil } f, err := os.Open(path) if err != nil { return nil, errors.Wrapf(err, token.NoPos, "load") } return f, nil } var skipDir = errors.Newf(token.NoPos, "skip directory") type walkFunc func(path string, entry iofs.DirEntry, err errors.Error) errors.Error func (fs *fileSystem) walk(root string, f walkFunc) error { info, err := fs.lstat(root) entry := iofs.FileInfoToDirEntry(info) if err != nil { err = f(root, entry, err) } else if !info.IsDir() { return errors.Newf(token.NoPos, "path %q is not a directory", root) } else { err = fs.walkRec(root, entry, f) } if err == skipDir { return nil } return err } func (fs *fileSystem) walkRec(path string, entry iofs.DirEntry, f walkFunc) errors.Error { if !entry.IsDir() { return f(path, entry, nil) } dir, err := fs.readDir(path) err1 := f(path, entry, err) // If err != nil, walk can't walk into this directory. // err1 != nil means walkFn want walk to skip this directory or stop walking. // Therefore, if one of err and err1 isn't nil, walk will return. if err != nil || err1 != nil { // The caller's behavior is controlled by the return value, which is decided // by walkFn. walkFn may ignore err and return nil. // If walkFn returns SkipDir, it will be handled by the caller. // So walk should return whatever walkFn returns. return err1 } for _, entry := range dir { filename := filepath.Join(path, entry.Name()) err = fs.walkRec(filename, entry, f) if err != nil { if !entry.IsDir() || err != skipDir { return err } } } return nil } var _ interface { iofs.FS iofs.ReadDirFS iofs.ReadFileFS module.OSRootFS } = (*ioFS)(nil) type ioFS struct { fs *fileSystem root string } func (fs *ioFS) OSRoot() string { return fs.root } func (fs *ioFS) Open(name string) (iofs.File, error) { fpath, err := fs.absPathFromFSPath(name) if err != nil { return nil, err } r, err := fs.fs.openFile(fpath) if err != nil { return nil, err // TODO convert filepath in error to fs path } return &ioFSFile{ fs: fs.fs, path: fpath, rc: r, }, nil } func (fs *ioFS) absPathFromFSPath(name string) (string, error) { if !iofs.ValidPath(name) { return "", fmt.Errorf("invalid io/fs path %q", name) } // Technically we should mimic Go's internal/safefilepath.fromFS // functionality here, but as we're using this in a relatively limited // context, we can just prohibit some characters. if strings.ContainsAny(name, ":\\") { return "", fmt.Errorf("invalid io/fs path %q", name) } return filepath.Join(fs.root, name), nil } // ReadDir implements [io/fs.ReadDirFS]. func (fs *ioFS) ReadDir(name string) ([]iofs.DirEntry, error) { fpath, err := fs.absPathFromFSPath(name) if err != nil { return nil, err } return fs.fs.readDir(fpath) } // ReadFile implements [io/fs.ReadFileFS]. func (fs *ioFS) ReadFile(name string) ([]byte, error) { fpath, err := fs.absPathFromFSPath(name) if err != nil { return nil, err } if fi := fs.fs.getOverlay(fpath); fi != nil { return bytes.Clone(fi.contents), nil } return os.ReadFile(fpath) } var _ module.ReadCUEFS = (*ioFS)(nil) // ReadCUEFile implements [module.ReadCUEFS] by // reading and updating the syntax file cache, which // is shared with the cache used by the [fileSystem.getCUESyntax] // method. func (fs *ioFS) ReadCUEFile(path string) (*ast.File, error) { fpath, err := fs.absPathFromFSPath(path) if err != nil { return nil, err } cache := fs.fs.fileCache cache.mu.Lock() entry, ok := cache.entries[fpath] cache.mu.Unlock() if ok { return entry.file, entry.err } var data []byte if fi := fs.fs.getOverlay(fpath); fi != nil { if fi.file != nil { // No need for a cache if we've got the contents in *ast.File // form already. return fi.file, nil } data = fi.contents } else { data, err = os.ReadFile(fpath) if err != nil { cache.mu.Lock() defer cache.mu.Unlock() cache.entries[fpath] = fileCacheEntry{nil, err} return nil, err } } return fs.fs.getCUESyntax(&build.File{ Filename: fpath, Encoding: build.CUE, // Form: build.Schema, Source: data, }) } // ioFSFile implements [io/fs.File] for the overlay filesystem. type ioFSFile struct { fs *fileSystem path string rc io.ReadCloser entries []iofs.DirEntry } var _ interface { iofs.File iofs.ReadDirFile } = (*ioFSFile)(nil) func (f *ioFSFile) Stat() (iofs.FileInfo, error) { return f.fs.stat(f.path) } func (f *ioFSFile) Read(buf []byte) (int, error) { return f.rc.Read(buf) } func (f *ioFSFile) Close() error { return f.rc.Close() } func (f *ioFSFile) ReadDir(n int) ([]iofs.DirEntry, error) { if f.entries == nil { entries, err := f.fs.readDir(f.path) if err != nil { return entries, err } if entries == nil { entries = []iofs.DirEntry{} } f.entries = entries } if n <= 0 { entries := f.entries f.entries = f.entries[len(f.entries):] return entries, nil } var err error if n >= len(f.entries) { n = len(f.entries) err = io.EOF } entries := f.entries[:n] f.entries = f.entries[n:] return entries, err } func (fs *fileSystem) getCUESyntax(bf *build.File) (*ast.File, error) { fs.fileCache.mu.Lock() defer fs.fileCache.mu.Unlock() if bf.Encoding != build.CUE { panic("getCUESyntax called with non-CUE file encoding") } // When it's a regular CUE file with no funny stuff going on, we // check and update the syntax cache. useCache := bf.Form == "" && bf.Interpretation == "" if useCache { if syntax, ok := fs.fileCache.entries[bf.Filename]; ok { return syntax.file, syntax.err } } d := encoding.NewDecoder(fs.fileCache.ctx, bf, &fs.fileCache.config) defer d.Close() // Note: CUE files can never have multiple file parts. f, err := d.File(), d.Err() if useCache { fs.fileCache.entries[bf.Filename] = fileCacheEntry{f, err} } return f, err } func newFileCache(c *Config) *fileCache { return &fileCache{ config: encoding.Config{ // Note: no need to pass Stdin, as we take care // always to pass a non-nil source when the file is "-". ParseFile: c.ParseFile, }, ctx: cuecontext.New(), entries: make(map[string]fileCacheEntry), } } // fileCache caches data derived from the file system. type fileCache struct { config encoding.Config ctx *cue.Context mu sync.Mutex entries map[string]fileCacheEntry } type fileCacheEntry struct { // TODO cache directory information too. // file caches the work involved when decoding a file into an *ast.File. // This can happen multiple times for the same file, for example when it is present in // multiple different build instances in the same directory hierarchy. file *ast.File err error } cue-lang-cue-db9cc73/cue/load/fs_test.go000066400000000000000000000026161474664451600201760ustar00rootroot00000000000000package load import ( "io/fs" "os" "path/filepath" "slices" "testing" "testing/fstest" "github.com/go-quicktest/qt" ) func TestIOFS(t *testing.T) { dir := t.TempDir() onDiskFiles := []string{ "foo/bar/a", "foo/bar/b", "foo/baz", "arble", } for _, f := range onDiskFiles { writeFile(t, filepath.Join(dir, f), f) } overlayFiles := []string{ "foo/bar/a", "foo/bar/c", "other/x", } overlay := map[string]Source{} for _, f := range overlayFiles { overlay[filepath.Join(dir, f)] = FromString(f + " overlay") } fsys, err := newFileSystem(&Config{ Dir: filepath.Join(dir, "foo"), Overlay: overlay, }) qt.Assert(t, qt.IsNil(err)) ffsys := fsys.ioFS(dir) err = fstest.TestFS(ffsys, append(slices.Clip(onDiskFiles), overlayFiles...)...) qt.Assert(t, qt.IsNil(err)) checked := make(map[string]bool) for _, f := range overlayFiles { data, err := fs.ReadFile(ffsys, f) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.Equals(string(data), f+" overlay")) checked[f] = true } for _, f := range onDiskFiles { if checked[f] { continue } data, err := fs.ReadFile(ffsys, f) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.Equals(string(data), f)) } } func writeFile(t *testing.T, fpath string, content string) { err := os.MkdirAll(filepath.Dir(fpath), 0o777) qt.Assert(t, qt.IsNil(err)) err = os.WriteFile(fpath, []byte(content), 0o666) qt.Assert(t, qt.IsNil(err)) } cue-lang-cue-db9cc73/cue/load/import.go000066400000000000000000000344741474664451600200500ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "cmp" "fmt" "io" "io/fs" pathpkg "path" "path/filepath" "slices" "strings" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/filetypes" "cuelang.org/go/mod/module" ) // importPkg returns details about the CUE package named by the import path, // interpreting local import paths relative to l.cfg.Dir. // If the path is a local import path naming a package that can be imported // using a standard import path, the returned package will set p.ImportPath // to that path. // // In the directory and ancestor directories up to including one with a // cue.mod file, all .cue files are considered part of the package except for: // // - files starting with _ or . (likely editor temporary files) // - files with build constraints not satisfied by the context // // If an error occurs, importPkg sets the error in the returned instance, // which then may contain partial information. // // pkgName indicates which packages to load. It supports the following // values: // // "" the default package for the directory, if only one // is present. // _ anonymous files (which may be marked with _) // * all packages func (l *loader) importPkg(pos token.Pos, p *build.Instance) []*build.Instance { retErr := func(errs errors.Error) []*build.Instance { // XXX: move this loop to ReportError for _, err := range errors.Errors(errs) { p.ReportError(err) } return []*build.Instance{p} } for _, item := range l.stk { if item == p.ImportPath { return retErr(&PackageError{Message: errors.NewMessagef("package import cycle not allowed")}) } } l.stk.Push(p.ImportPath) defer l.stk.Pop() cfg := l.cfg ctxt := cfg.fileSystem if p.Err != nil { return []*build.Instance{p} } fp := newFileProcessor(cfg, p, l.tagger) if p.PkgName == "" { if l.cfg.Package == "*" { fp.allPackages = true p.PkgName = "_" } else { p.PkgName = l.cfg.Package } } if p.PkgName != "" { // If we have an explicit package name, we can ignore other packages. fp.ignoreOther = true } var dirs [][2]string genDir := GenPath(cfg.ModuleRoot) if strings.HasPrefix(p.Dir, genDir) { dirs = append(dirs, [2]string{genDir, p.Dir}) // && p.PkgName != "_" for _, sub := range []string{"pkg", "usr"} { rel, err := filepath.Rel(genDir, p.Dir) if err != nil { // should not happen return retErr(errors.Wrapf(err, token.NoPos, "invalid path")) } base := filepath.Join(cfg.ModuleRoot, modDir, sub) dir := filepath.Join(base, rel) dirs = append(dirs, [2]string{base, dir}) } } else { dirs = append(dirs, [2]string{cfg.ModuleRoot, p.Dir}) } found := false for _, d := range dirs { info, err := ctxt.stat(d[1]) if err == nil && info.IsDir() { found = true break } } if !found { return retErr( &PackageError{ Message: errors.NewMessagef("cannot find package %q", p.DisplayPath), }) } // This algorithm assumes that multiple directories within cue.mod/*/ // have the same module scope and that there are no invalid modules. inModule := false // if pkg == "_" for _, d := range dirs { if l.cfg.findModRoot(d[1]) != "" { inModule = true break } } // Walk the parent directories up to the module root to add their files as well, // since a package foo/bar/baz inherits from parent packages foo/bar and foo. // See https://cuelang.org/docs/concept/modules-packages-instances/#instances. for _, d := range dirs { dir := filepath.Clean(d[1]) for { sd, ok := l.dirCachedBuildFiles[dir] if !ok { sd = l.scanDir(dir) l.dirCachedBuildFiles[dir] = sd } if err := sd.err; err != nil { if errors.Is(err, fs.ErrNotExist) { break } return retErr(errors.Wrapf(err, token.NoPos, "import failed reading dir %v", dir)) } for _, name := range sd.filenames { file, err := filetypes.ParseFileAndType(name, "", filetypes.Input) if err != nil { p.UnknownFiles = append(p.UnknownFiles, &build.File{ Filename: name, ExcludeReason: errors.Newf(token.NoPos, "unknown filetype"), }) } else { fp.add(dir, file, 0) } } if p.PkgName == "" || !inModule || l.cfg.isModRoot(dir) || dir == d[0] { break } // From now on we just ignore files that do not belong to the same // package. fp.ignoreOther = true parent, _ := filepath.Split(dir) parent = filepath.Clean(parent) if parent == dir || len(parent) < len(d[0]) { break } dir = parent } } all := []*build.Instance{} for _, p := range fp.pkgs { impPath, err := addImportQualifier(importPath(p.ImportPath), p.PkgName) p.ImportPath = string(impPath) if err != nil { p.ReportError(errors.Promote(err, "")) } if len(p.BuildFiles) == 0 && len(p.IgnoredFiles) == 0 && len(p.OrphanedFiles) == 0 && len(p.InvalidFiles) == 0 && len(p.UnknownFiles) == 0 { // The package has no files in it. This can happen // when the default package added in newFileProcessor // doesn't have any associated files. continue } all = append(all, p) rewriteFiles(p, cfg.ModuleRoot, false) if errs := fp.finalize(p); errs != nil { p.ReportError(errs) return all } l.addFiles(p) _ = p.Complete() } slices.SortFunc(all, func(a, b *build.Instance) int { // Instances may share the same directory but have different package names. // Sort by directory first, then by package name. if c := cmp.Compare(a.Dir, b.Dir); c != 0 { return c } return cmp.Compare(a.PkgName, b.PkgName) }) return all } func (l *loader) scanDir(dir string) cachedDirFiles { files, err := l.cfg.fileSystem.readDir(dir) if err != nil { return cachedDirFiles{ err: err, } } filenames := make([]string, 0, len(files)) for _, f := range files { if f.IsDir() { continue } name := f.Name() if name == "-" { // The name "-" has a special significance to the file types // logic, but only when specified directly on the command line. // We don't want an actual file named "-" to have special // significant, so avoid that by making sure we don't see a naked "-" // even when a file named "-" is present in a directory. name = "./-" } filenames = append(filenames, name) } return cachedDirFiles{ filenames: filenames, } } func setFileSource(cfg *Config, f *build.File) error { if f.Source != nil { return nil } fullPath := f.Filename if fullPath == "-" { b, err := io.ReadAll(cfg.stdin()) if err != nil { return errors.Newf(token.NoPos, "read stdin: %v", err) } f.Source = b return nil } if !filepath.IsAbs(fullPath) { fullPath = filepath.Join(cfg.Dir, fullPath) // Ensure that encoding.NewDecoder will work correctly. f.Filename = fullPath } if fi := cfg.fileSystem.getOverlay(fullPath); fi != nil { if fi.file != nil { f.Source = fi.file } else { f.Source = fi.contents } } return nil } func (l *loader) loadFunc() build.LoadFunc { if l.cfg.SkipImports { return nil } return l._loadFunc } func (l *loader) _loadFunc(pos token.Pos, path string) *build.Instance { impPath := importPath(path) if isLocalImport(path) { return l.cfg.newErrInstance(errors.Newf(pos, "relative import paths not allowed (%q)", path)) } if isStdlibPackage(path) { // It looks like a builtin. return nil } p := l.newInstance(pos, impPath) _ = l.importPkg(pos, p) return p } // newRelInstance returns a build instance from the given // relative import path. func (l *loader) newRelInstance(pos token.Pos, path, pkgName string) *build.Instance { if !isLocalImport(path) { panic(fmt.Errorf("non-relative import path %q passed to newRelInstance", path)) } p := l.cfg.Context.NewInstance(path, l.loadFunc()) p.PkgName = pkgName p.DisplayPath = filepath.ToSlash(path) // p.ImportPath = string(dir) // compute unique ID. p.Root = l.cfg.ModuleRoot p.Module = l.cfg.Module var err errors.Error if path != cleanImport(path) { err = errors.Append(err, l.errPkgf(nil, "non-canonical import path: %q should be %q", path, pathpkg.Clean(path))) } dir := filepath.Join(l.cfg.Dir, filepath.FromSlash(path)) if pkgPath, e := importPathFromAbsDir(l.cfg, dir, path); e != nil { // Detect later to keep error messages consistent. } else { // Add package qualifier if the configuration requires it. name := l.cfg.Package switch name { case "_", "*": name = "" } pkgPath, e := addImportQualifier(pkgPath, name) if e != nil { // Detect later to keep error messages consistent. } else { p.ImportPath = string(pkgPath) } } p.Dir = dir if filepath.IsAbs(path) || strings.HasPrefix(path, "/") { err = errors.Append(err, errors.Newf(pos, "absolute import path %q not allowed", path)) } if err != nil { p.Err = errors.Append(p.Err, err) p.Incomplete = true } return p } func importPathFromAbsDir(c *Config, absDir string, origPath string) (importPath, error) { if c.ModuleRoot == "" { return "", fmt.Errorf("cannot determine import path for %q (root undefined)", origPath) } dir := filepath.Clean(absDir) if !strings.HasPrefix(dir, c.ModuleRoot) { return "", fmt.Errorf("cannot determine import path for %q (dir outside of root)", origPath) } pkg := filepath.ToSlash(dir[len(c.ModuleRoot):]) switch { case strings.HasPrefix(pkg, "/cue.mod/"): pkg = pkg[len("/cue.mod/"):] if pkg == "" { return "", fmt.Errorf("invalid package %q (root of %s)", origPath, modDir) } case c.Module == "": return "", fmt.Errorf("cannot determine import path for %q (no module)", origPath) default: impPath := module.ParseImportPath(c.Module) impPath.Path += pkg impPath.Qualifier = "" pkg = impPath.String() } return importPath(pkg), nil } func (l *loader) newInstance(pos token.Pos, p importPath) *build.Instance { dir, modPath, err := l.absDirFromImportPath(pos, p) i := l.cfg.Context.NewInstance(dir, l.loadFunc()) i.Err = errors.Append(i.Err, err) i.Dir = dir parts := module.ParseImportPath(string(p)) i.PkgName = parts.Qualifier if i.PkgName == "" { i.Err = errors.Append(i.Err, l.errPkgf([]token.Pos{pos}, "cannot determine package name for %q; set it explicitly with ':'", p)) } else if i.PkgName == "_" { i.Err = errors.Append(i.Err, l.errPkgf([]token.Pos{pos}, "_ is not a valid import path qualifier in %q", p)) } i.DisplayPath = string(p) i.ImportPath = string(p) i.Root = l.cfg.ModuleRoot i.Module = modPath return i } // absDirFromImportPath converts a giving import path to an absolute directory // and a package name. The root directory must be set. // // The returned directory may not exist. func (l *loader) absDirFromImportPath(pos token.Pos, p importPath) (dir string, modPath string, _ errors.Error) { dir, modPath, err := l.absDirFromImportPath1(pos, p) if err != nil { // Any error trying to determine the package location // is a PackageError. return "", "", l.errPkgf([]token.Pos{pos}, "%s", err.Error()) } return dir, modPath, nil } func (l *loader) absDirFromImportPath1(pos token.Pos, p importPath) (absDir string, modPath string, err error) { if p == "" { return "", "", fmt.Errorf("empty import path") } if l.cfg.ModuleRoot == "" { return "", "", fmt.Errorf("cannot import %q (root undefined)", p) } if isStdlibPackage(string(p)) { return "", "", fmt.Errorf("standard library import path %q cannot be imported as a CUE package", p) } if l.pkgs == nil { return "", "", fmt.Errorf("imports are unavailable because there is no cue.mod/module.cue file") } // Extract the package name. parts := module.ParseImportPath(string(p)) unqualified := parts.Unqualified().String() // TODO predicate registry-aware lookup on module.cue-declared CUE version? // Note: use the canonical form of the import path because // that's the form passed to [modpkgload.LoadPackages] // and hence it's available by that name via Pkg. pkg := l.pkgs.Pkg(parts.Canonical().String()) // TODO(mvdan): using "unqualified" for the errors below doesn't seem right, // should we not be using either the original path or the canonical path? // The unqualified import path should only be used for filepath.FromSlash further below. if pkg == nil { return "", "", fmt.Errorf("no dependency found for package %q", unqualified) } if err := pkg.Error(); err != nil { return "", "", fmt.Errorf("cannot find package %q: %v", unqualified, err) } if mv := pkg.Mod(); mv.IsLocal() { // It's a local package that's present inside one or both of the gen, usr or pkg // directories. Even though modpkgload tells us exactly what those directories // are, the rest of the cue/load logic expects only a single directory for now, // so just use that. absDir = filepath.Join(GenPath(l.cfg.ModuleRoot), parts.Path) } else { locs := pkg.Locations() if len(locs) > 1 { return "", "", fmt.Errorf("package %q unexpectedly found in multiple locations", unqualified) } if len(locs) == 0 { return "", "", fmt.Errorf("no location found for package %q", unqualified) } var err error absDir, err = absPathForSourceLoc(locs[0]) if err != nil { return "", "", fmt.Errorf("cannot determine source directory for package %q: %v", unqualified, err) } } return absDir, pkg.Mod().Path(), nil } func absPathForSourceLoc(loc module.SourceLoc) (string, error) { osfs, ok := loc.FS.(module.OSRootFS) if !ok { return "", fmt.Errorf("cannot get absolute path for FS of type %T", loc.FS) } osPath := osfs.OSRoot() if osPath == "" { return "", fmt.Errorf("cannot get absolute path for FS of type %T", loc.FS) } return filepath.Join(osPath, loc.Dir), nil } // isStdlibPackage reports whether pkgPath looks like // an import from the standard library. func isStdlibPackage(pkgPath string) bool { firstElem, _, _ := strings.Cut(pkgPath, "/") if firstElem == "" { return false // absolute paths like "/foo/bar" } // Paths like ".foo/bar", "./foo/bar", or "foo.com/bar" are not standard library import paths. return strings.IndexByte(firstElem, '.') == -1 } cue-lang-cue-db9cc73/cue/load/import_test.go000066400000000000000000000056571474664451600211100ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "fmt" "os" "path/filepath" "reflect" "testing" "cuelang.org/go/cue/build" ) func testdata(elems ...string) string { return filepath.Join(append([]string{"testdata"}, elems...)...) } var pkgRootDir, _ = os.Getwd() func getInst(pkg, cwd string) (*build.Instance, error) { insts := Instances([]string{pkg}, &Config{ // Set ModuleRoot as well; otherwise we walk the parent directories // all the way to the root of the git repository, causing Go's test caching // to never kick in, as the .git directory almost always changes. // Moreover, it's extra work that isn't useful to the tests. // // Note that we can't set ModuleRoot to cwd because if ModuleRoot is // set, the logic will only look for a module file in that exact directory. // So we set it to the module root actually used by all the callers of getInst: ./testdata/testmod. ModuleRoot: filepath.Join(pkgRootDir, testdata("testmod")), Dir: cwd, }) if len(insts) != 1 { return nil, fmt.Errorf("expected one instance, got %d", len(insts)) } inst := insts[0] return inst, inst.Err } func TestEmptyImport(t *testing.T) { path := testdata("testmod", "hello") p, err := getInst("", path) if err == nil { t.Fatal(`Import("") returned nil error.`) } if p == nil { t.Fatal(`Import("") returned nil package.`) } if p.DisplayPath != "" { t.Fatalf("DisplayPath=%q, want %q.", p.DisplayPath, "") } } func TestEmptyFolderImport(t *testing.T) { path := testdata("testmod", "empty") _, err := getInst(".", path) if _, ok := err.(*NoFilesError); !ok { t.Fatalf(`Import(%q) did not return NoCUEError, but instead %#v (%v)`, path, err, err) } } func TestMultiplePackageImport(t *testing.T) { path := testdata("testmod", "multi") _, err := getInst(".", path) mpe, ok := err.(*MultiplePackageError) if !ok { t.Fatalf(`Import(%q) did not return MultiplePackageError, but instead %#v (%v)`, path, err, err) } mpe.Dir = "" want := &MultiplePackageError{ Packages: []string{"main", "test_package"}, Files: []string{"file.cue", "file_appengine.cue"}, } if !reflect.DeepEqual(mpe, want) { t.Errorf("got %#v; want %#v", mpe, want) } } func TestLocalDirectory(t *testing.T) { p, err := getInst(".", testdata("testmod", "hello")) if err != nil { t.Fatal(err) } if p.DisplayPath != "." { t.Fatalf("DisplayPath=%q, want %q", p.DisplayPath, ".") } } cue-lang-cue-db9cc73/cue/load/instances.go000066400000000000000000000156751474664451600205270ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "context" "fmt" "io/fs" "slices" "strconv" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/internal/filetypes" "cuelang.org/go/internal/mod/modimports" "cuelang.org/go/internal/mod/modpkgload" "cuelang.org/go/internal/mod/modrequirements" "cuelang.org/go/mod/module" ) // Instances returns the instances named by the command line arguments 'args'. // If errors occur trying to load an instance it is returned with Incomplete // set. Errors directly related to loading the instance are recorded in this // instance, but errors that occur loading dependencies are recorded in these // dependencies. func Instances(args []string, c *Config) []*build.Instance { ctx := context.TODO() if c == nil { c = &Config{} } newC, err := c.complete() if err != nil { return []*build.Instance{c.newErrInstance(err)} } c = newC if len(args) == 0 { args = []string{"."} } // TODO: This requires packages to be placed before files. At some point this // could be relaxed. i := 0 for ; i < len(args) && filetypes.IsPackage(args[i]); i++ { } pkgArgs := args[:i] otherArgs := args[i:] otherFiles, err := filetypes.ParseArgs(otherArgs) if err != nil { return []*build.Instance{c.newErrInstance(err)} } for _, f := range otherFiles { if err := setFileSource(c, f); err != nil { return []*build.Instance{c.newErrInstance(err)} } } if c.Package != "" && c.Package != "_" && c.Package != "*" { // The caller has specified an explicit package to load. // This is essentially the same as passing an explicit package // qualifier to all package arguments that don't already have // one. We add that qualifier here so that there's a distinction // between package paths specified as arguments, which // have the qualifier added, and package paths that are dependencies // of those, which don't. pkgArgs1 := make([]string, 0, len(pkgArgs)) for _, p := range pkgArgs { if ip := module.ParseImportPath(p); !ip.ExplicitQualifier { ip.Qualifier = c.Package p = ip.String() } pkgArgs1 = append(pkgArgs1, p) } pkgArgs = pkgArgs1 } tg := newTagger(c) // Pass all arguments that look like packages to loadPackages // so that they'll be available when looking up the packages // that are specified on the command line. expandedPaths, err := expandPackageArgs(c, pkgArgs, c.Package, tg) if err != nil { return []*build.Instance{c.newErrInstance(err)} } var pkgs *modpkgload.Packages if !c.SkipImports { pkgs, err = loadPackages(ctx, c, expandedPaths, otherFiles, tg) if err != nil { return []*build.Instance{c.newErrInstance(err)} } } l := newLoader(c, tg, pkgs) if c.Context == nil { opts := []build.Option{ build.ParseFile(c.ParseFile), } if f := l.loadFunc(); l != nil { opts = append(opts, build.Loader(f)) } c.Context = build.NewContext(opts...) } a := []*build.Instance{} if len(pkgArgs) > 0 { for _, m := range l.importPaths(pkgArgs) { if m.Err != nil { inst := c.newErrInstance(m.Err) a = append(a, inst) continue } a = append(a, m.Pkgs...) } } if len(otherFiles) > 0 { a = append(a, l.cueFilesPackage(otherFiles)) } for _, p := range a { tags, err := findTags(p) if err != nil { p.ReportError(err) } tg.tags = append(tg.tags, tags...) } // TODO(api): have API call that returns an error which is the aggregate // of all build errors. Certain errors, like these, hold across builds. if err := tg.injectTags(c.Tags); err != nil { for _, p := range a { p.ReportError(err) } return a } if tg.replacements == nil { return a } for _, p := range a { for _, f := range p.Files { ast.Walk(f, nil, func(n ast.Node) { if ident, ok := n.(*ast.Ident); ok { if v, ok := tg.replacements[ident.Node]; ok { ident.Node = v } } }) } } return a } // loadPackages returns packages loaded from the given package list and also // including imports from the given build files. func loadPackages( ctx context.Context, cfg *Config, pkgs []resolvedPackageArg, otherFiles []*build.File, tg *tagger, ) (*modpkgload.Packages, error) { if cfg.modFile == nil || cfg.modFile.Module == "" { return nil, nil } mainModPath := cfg.modFile.QualifiedModule() reqs := modrequirements.NewRequirements( mainModPath, cfg.Registry, cfg.modFile.DepVersions(), cfg.modFile.DefaultMajorVersions(), ) mainModLoc := module.SourceLoc{ FS: cfg.fileSystem.ioFS(cfg.ModuleRoot), Dir: ".", } pkgPaths := make(map[string]bool) // Add any packages specified directly on the command line. for _, pkg := range pkgs { pkgPaths[pkg.resolvedCanonical] = true } // Add any imports found in other files. for _, f := range otherFiles { if f.Encoding != build.CUE { // not a CUE file; assume it has no imports for now. continue } syntax, err := cfg.fileSystem.getCUESyntax(f) if err != nil { return nil, fmt.Errorf("cannot get syntax for %q: %w", f.Filename, err) } for _, imp := range syntax.Imports { pkgPath, err := strconv.Unquote(imp.Path.Value) if err != nil { // Should never happen. return nil, fmt.Errorf("invalid import path %q in %s", imp.Path.Value, f.Filename) } // Canonicalize the path. pkgPath = module.ParseImportPath(pkgPath).Canonical().String() pkgPaths[pkgPath] = true } } // TODO use maps.Keys when we can. pkgPathSlice := make([]string, 0, len(pkgPaths)) for p := range pkgPaths { pkgPathSlice = append(pkgPathSlice, p) } slices.Sort(pkgPathSlice) return modpkgload.LoadPackages( ctx, cfg.Module, mainModLoc, reqs, cfg.Registry, pkgPathSlice, func(pkgPath string, mod module.Version, fsys fs.FS, mf modimports.ModuleFile) bool { if !cfg.Tools && strings.HasSuffix(mf.FilePath, "_tool.cue") { return false } isTest := strings.HasSuffix(mf.FilePath, "_test.cue") var tagIsSet func(string) bool if mod.Path() == mainModPath { // In the main module. if isTest && !cfg.Tests { return false } tagIsSet = tg.tagIsSet } else { // Outside the main module. if isTest { // Don't traverse test files outside the main module return false } // Treat all build tag keys as unset. tagIsSet = func(string) bool { return false } } if err := shouldBuildFile(mf.Syntax, tagIsSet); err != nil { // Later build logic should pick up and report the same error. return false } return true }, ), nil } cue-lang-cue-db9cc73/cue/load/loader.go000066400000000000000000000074531474664451600200010ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load // Files in this package are to a large extent based on Go files from the following // Go packages: // - cmd/go/internal/load // - go/build import ( "path/filepath" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/mod/modpkgload" ) type loader struct { cfg *Config tagger *tagger stk importStack pkgs *modpkgload.Packages // dirCachedBuildFiles caches the work involved when reading a // directory. It is keyed by directory name. When we descend into // subdirectories to load patterns such as ./... we often end up // loading parent directories many times over; this cache // amortizes that work. dirCachedBuildFiles map[string]cachedDirFiles } type cachedDirFiles struct { err errors.Error filenames []string } func newLoader(c *Config, tg *tagger, pkgs *modpkgload.Packages) *loader { return &loader{ cfg: c, tagger: tg, pkgs: pkgs, dirCachedBuildFiles: make(map[string]cachedDirFiles), } } func (l *loader) abs(filename string) string { if !isLocalImport(filename) { return filename } return filepath.Join(l.cfg.Dir, filename) } func (l *loader) errPkgf(importPos []token.Pos, format string, args ...interface{}) *PackageError { err := &PackageError{ ImportStack: l.stk.Copy(), Message: errors.NewMessagef(format, args...), } err.fillPos(l.cfg.Dir, importPos) return err } // cueFilesPackage creates a package for building a collection of CUE files // (typically named on the command line). func (l *loader) cueFilesPackage(files []*build.File) *build.Instance { // ModInit() // TODO: support modules pkg := l.cfg.Context.NewInstance(l.cfg.Dir, l.loadFunc()) for _, bf := range files { f := bf.Filename if f == "-" { continue } if !filepath.IsAbs(f) { f = filepath.Join(l.cfg.Dir, f) } fi, err := l.cfg.fileSystem.stat(f) if err != nil { return l.cfg.newErrInstance(errors.Wrapf(err, token.NoPos, "could not find file %v", f)) } if fi.IsDir() { return l.cfg.newErrInstance(errors.Newf(token.NoPos, "file is a directory %v", f)) } } fp := newFileProcessor(l.cfg, pkg, l.tagger) if l.cfg.Package == "*" { fp.allPackages = true pkg.PkgName = "_" } for _, bf := range files { fp.add(l.cfg.Dir, bf, allowAnonymous|allowExcludedFiles) } // TODO: ModImportFromFiles(files) pkg.Dir = l.cfg.Dir rewriteFiles(pkg, pkg.Dir, true) for _, err := range errors.Errors(fp.finalize(pkg)) { // ImportDir(&ctxt, dir, 0) var x *NoFilesError if len(pkg.OrphanedFiles) == 0 || !errors.As(err, &x) { pkg.ReportError(err) } } // TODO: Support module importing. // if ModDirImportPath != nil { // // Use the effective import path of the directory // // for deciding visibility during pkg.load. // bp.ImportPath = ModDirImportPath(dir) // } pkg.User = true l.addFiles(pkg) _ = pkg.Complete() pkg.DisplayPath = "command-line-arguments" return pkg } // addFiles populates p.Files by reading CUE syntax from p.BuildFiles. func (l *loader) addFiles(p *build.Instance) { for _, bf := range p.BuildFiles { f, err := l.cfg.fileSystem.getCUESyntax(bf) if err != nil { p.ReportError(errors.Promote(err, "load")) } _ = p.AddSyntax(f) } } cue-lang-cue-db9cc73/cue/load/loader_common.go000066400000000000000000000263631474664451600213520ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "cmp" pathpkg "path" "path/filepath" "slices" "strconv" "strings" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" ) // An importMode controls the behavior of the Import method. type importMode uint const ( allowAnonymous = 1 << iota allowExcludedFiles ) var errExclude = errors.New("file rejected") type cueError = errors.Error type excludeError struct { cueError } func (e excludeError) Is(err error) bool { return err == errExclude } func rewriteFiles(p *build.Instance, root string, isLocal bool) { p.Root = root normalizeFiles(p.BuildFiles) normalizeFiles(p.IgnoredFiles) normalizeFiles(p.OrphanedFiles) normalizeFiles(p.InvalidFiles) normalizeFiles(p.UnknownFiles) } // normalizeFiles sorts the files so that files contained by a parent directory // always come before files contained in sub-directories, and that filenames in // the same directory are sorted lexically byte-wise, like Go's `<` operator. func normalizeFiles(files []*build.File) { slices.SortFunc(files, func(a, b *build.File) int { fa := a.Filename fb := b.Filename ca := strings.Count(fa, string(filepath.Separator)) cb := strings.Count(fb, string(filepath.Separator)) if c := cmp.Compare(ca, cb); c != 0 { return c } return cmp.Compare(fa, fb) }) } func cleanImport(path string) string { orig := path path = pathpkg.Clean(path) if strings.HasPrefix(orig, "./") && path != ".." && !strings.HasPrefix(path, "../") { path = "./" + path } return path } // An importStack is a stack of import paths, possibly with the suffix " (test)" appended. // The import path of a test package is the import path of the corresponding // non-test package with the suffix "_test" added. type importStack []string func (s *importStack) Push(p string) { *s = append(*s, p) } func (s *importStack) Pop() { *s = (*s)[0 : len(*s)-1] } func (s *importStack) Copy() []string { return slices.Clone(*s) } type fileProcessor struct { firstFile string imported map[string][]token.Pos ignoreOther bool // ignore files from other packages allPackages bool c *fileProcessorConfig tagger *tagger pkgs map[string]*build.Instance pkg *build.Instance err errors.Error } type fileProcessorConfig = Config func newFileProcessor(c *fileProcessorConfig, p *build.Instance, tg *tagger) *fileProcessor { return &fileProcessor{ imported: make(map[string][]token.Pos), c: c, pkgs: map[string]*build.Instance{"_": p}, pkg: p, tagger: tg, } } func countCUEFiles(c *fileProcessorConfig, p *build.Instance) int { count := len(p.BuildFiles) for _, f := range p.IgnoredFiles { if c.Tools && strings.HasSuffix(f.Filename, "_tool.cue") { count++ } if c.Tests && strings.HasSuffix(f.Filename, "_test.cue") { count++ } } return count } func (fp *fileProcessor) finalize(p *build.Instance) errors.Error { if fp.err != nil { return fp.err } if countCUEFiles(fp.c, p) == 0 && !fp.c.DataFiles && (p.PkgName != "_" || !fp.allPackages) { fp.err = errors.Append(fp.err, &NoFilesError{Package: p, ignored: len(p.IgnoredFiles) > 0}) return fp.err } p.ImportPaths, _ = cleanImports(fp.imported) return nil } // add adds the given file to the appropriate package in fp. func (fp *fileProcessor) add(root string, file *build.File, mode importMode) { fullPath := file.Filename if fullPath != "-" { if !filepath.IsAbs(fullPath) { fullPath = filepath.Join(root, fullPath) } file.Filename = fullPath } base := filepath.Base(fullPath) // special * and _ p := fp.pkg // default package // sameDir holds whether the file should be considered to be // part of the same directory as the default package. This is // true when the file is part of the original package directory // or when allowExcludedFiles is specified, signifying that the // file is part of an explicit set of files provided on the // command line. sameDir := filepath.Dir(fullPath) == p.Dir || (mode&allowExcludedFiles) != 0 // badFile := func(p *build.Instance, err errors.Error) bool { badFile := func(err errors.Error) { fp.err = errors.Append(fp.err, err) file.ExcludeReason = fp.err p.InvalidFiles = append(p.InvalidFiles, file) } if err := setFileSource(fp.c, file); err != nil { badFile(errors.Promote(err, "")) return } if file.Encoding != build.CUE { // Not a CUE file. if sameDir { p.OrphanedFiles = append(p.OrphanedFiles, file) } return } if (mode & allowExcludedFiles) == 0 { var badPrefix string for _, prefix := range []string{".", "_"} { if strings.HasPrefix(base, prefix) { badPrefix = prefix } } if badPrefix != "" { if !sameDir { return } file.ExcludeReason = errors.Newf(token.NoPos, "filename starts with a '%s'", badPrefix) if file.Interpretation == "" { p.IgnoredFiles = append(p.IgnoredFiles, file) } else { p.OrphanedFiles = append(p.OrphanedFiles, file) } return } } // Note: when path is "-" (stdin), it will already have // been read and file.Source set to the resulting data // by setFileSource. pf, perr := fp.c.fileSystem.getCUESyntax(file) if perr != nil { badFile(errors.Promote(perr, "add failed")) return } pkg := pf.PackageName() if pkg == "" { pkg = "_" } pos := pf.Pos() switch { case pkg == p.PkgName && (sameDir || pkg != "_"): // We've got the exact package that's being looked for. // It will already be present in fp.pkgs. case mode&allowAnonymous != 0 && sameDir: // It's an anonymous file that's not in a parent directory. case fp.allPackages && pkg != "_": q := fp.pkgs[pkg] if q == nil && !sameDir { // It's a file in a parent directory that doesn't correspond // to a package in the original directory. return } if q == nil { q = fp.c.Context.NewInstance(p.Dir, nil) q.PkgName = pkg q.DisplayPath = p.DisplayPath q.ImportPath = p.ImportPath + ":" + pkg q.Root = p.Root q.Module = p.Module fp.pkgs[pkg] = q } p = q case pkg != "_": // We're loading a single package and we either haven't matched // the earlier selected package or we haven't selected a package // yet. In either case, the default package is the one we want to use. default: if sameDir { file.ExcludeReason = excludeError{errors.Newf(pos, "no package name")} p.IgnoredFiles = append(p.IgnoredFiles, file) } return } if !fp.c.AllCUEFiles { tagIsSet := fp.tagger.tagIsSet if p.Module != "" && p.Module != fp.c.Module { // The file is outside the main module so treat all build tag keys as unset. // Note that if there's no module, we don't consider it to be outside // the main module, because otherwise @if tags in non-package files // explicitly specified on the command line will not work. tagIsSet = func(string) bool { return false } } if err := shouldBuildFile(pf, tagIsSet); err != nil { if !errors.Is(err, errExclude) { fp.err = errors.Append(fp.err, err) } file.ExcludeReason = err p.IgnoredFiles = append(p.IgnoredFiles, file) return } } if pkg != "" && pkg != "_" { if p.PkgName == "" { p.PkgName = pkg fp.firstFile = base } else if pkg != p.PkgName { if fp.ignoreOther { file.ExcludeReason = excludeError{errors.Newf(pos, "package is %s, want %s", pkg, p.PkgName)} p.IgnoredFiles = append(p.IgnoredFiles, file) return } if !fp.allPackages { badFile(&MultiplePackageError{ Dir: p.Dir, Packages: []string{p.PkgName, pkg}, Files: []string{fp.firstFile, base}, }) return } } } isTest := strings.HasSuffix(base, "_test"+cueSuffix) isTool := strings.HasSuffix(base, "_tool"+cueSuffix) for _, spec := range pf.Imports { quoted := spec.Path.Value path, err := strconv.Unquote(quoted) if err != nil { badFile(errors.Newf( spec.Path.Pos(), "%s: parser returned invalid quoted string: <%s>", fullPath, quoted, )) } if !isTest || fp.c.Tests { fp.imported[path] = append(fp.imported[path], spec.Pos()) } } switch { case isTest: if fp.c.Tests { p.BuildFiles = append(p.BuildFiles, file) } else { file.ExcludeReason = excludeError{errors.Newf(pos, "_test.cue files excluded in non-test mode")} p.IgnoredFiles = append(p.IgnoredFiles, file) } case isTool: if fp.c.Tools { p.BuildFiles = append(p.BuildFiles, file) } else { file.ExcludeReason = excludeError{errors.Newf(pos, "_tool.cue files excluded in non-cmd mode")} p.IgnoredFiles = append(p.IgnoredFiles, file) } default: p.BuildFiles = append(p.BuildFiles, file) } } func cleanImports(m map[string][]token.Pos) ([]string, map[string][]token.Pos) { all := make([]string, 0, len(m)) for path := range m { all = append(all, path) } slices.Sort(all) return all, m } // isLocalImport reports whether the import path is // a local import path, like ".", "..", "./foo", or "../foo". func isLocalImport(path string) bool { return path == "." || path == ".." || strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../") } // warnUnmatched warns about patterns that didn't match any packages. func warnUnmatched(matches []*match) { for _, m := range matches { if len(m.Pkgs) == 0 { m.Err = errors.Newf(token.NoPos, "cue: %q matched no packages", m.Pattern) } } } // cleanPatterns returns the patterns to use for the given // command line. It canonicalizes the patterns but does not // evaluate any matches. func cleanPatterns(patterns []string) []string { if len(patterns) == 0 { return []string{"."} } var out []string for _, a := range patterns { // Arguments are supposed to be import paths, but // as a courtesy to Windows developers, rewrite \ to / // in command-line arguments. Handles .\... and so on. if filepath.Separator == '\\' { a = strings.Replace(a, `\`, `/`, -1) } // Put argument in canonical form, but preserve leading "./". if strings.HasPrefix(a, "./") { a = "./" + pathpkg.Clean(a) if a == "./." { a = "." } } else if a != "" { a = pathpkg.Clean(a) } out = append(out, a) } return out } // isMetaPackage checks if name is a reserved package name that expands to multiple packages. // TODO: none of these package names are actually recognized anywhere else // and at least one (cmd) doesn't seem like it belongs in the CUE world. func isMetaPackage(name string) bool { return name == "std" || name == "cmd" || name == "all" } // hasFilepathPrefix reports whether the path s begins with the // elements in prefix. func hasFilepathPrefix(s, prefix string) bool { switch { default: return false case len(s) == len(prefix): return s == prefix case len(s) > len(prefix): if prefix != "" && prefix[len(prefix)-1] == filepath.Separator { return strings.HasPrefix(s, prefix) } return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix } } cue-lang-cue-db9cc73/cue/load/loader_test.go000066400000000000000000000550571474664451600210430ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "bytes" "fmt" "os" "path/filepath" "strings" "sync" "testing" "text/template" "unicode" "github.com/go-quicktest/qt" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/internal/tdtest" ) func init() { // The user running `go test` might have a broken environment, // such as an invalid $CUE_REGISTRY like the one below, // or a broken $DOCKER_CONFIG/config.json due to syntax errors. // Go tests should be hermetic by explicitly setting load.Config.Env; // catch any that do not by leaving a broken $CUE_REGISTRY in os.Environ. os.Setenv("CUE_REGISTRY", "inline:{") } // TestLoad is an end-to-end test. func TestLoad(t *testing.T) { cwd, err := os.Getwd() if err != nil { t.Fatal(err) } testdataDir := testdata("testmod") dirCfg := &Config{ Dir: testdataDir, Tools: true, } badModCfg := &Config{ Dir: testdata("badmod"), } type loadTest struct { name string cfg *Config args []string want string } testCases := []loadTest{{ name: "BadModuleFile", cfg: badModCfg, args: []string{"."}, want: `err: module: 2 errors in empty disjunction: module: conflicting values 123 and "" (mismatched types int and string): $CWD/testdata/badmod/cue.mod/module.cue:2:9 cuelang.org/go/mod/modfile/schema.cue:56:22 module: conflicting values 123 and string (mismatched types int and string): $CWD/testdata/badmod/cue.mod/module.cue:2:9 cuelang.org/go/mod/modfile/schema.cue:56:12 cuelang.org/go/mod/modfile/schema.cue:98:12 path: "" module: "" root: "" dir: "" display:""`, }, { name: "DefaultPackage", // Even though the directory is called testdata, the last path in // the module is test. So "package test" is correctly the default // package of this directory. cfg: dirCfg, args: nil, want: `path: mod.test/test@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:. files: $CWD/testdata/testmod/test.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { name: "DefaultPackageWithExplicitDotArgument", // Even though the directory is called testdata, the last path in // the module is test. So "package test" is correctly the default // package of this directory. cfg: dirCfg, args: []string{"."}, want: `path: mod.test/test@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:. files: $CWD/testdata/testmod/test.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { name: "RelativeImportPathWildcard", cfg: dirCfg, args: []string{"./other/..."}, want: `err: import failed: relative import paths not allowed ("./file"): $CWD/testdata/testmod/other/main.cue:6:2 path: "" module: mod.test/test@v0 root: $CWD/testdata/testmod dir: "" display:""`}, { name: "NoMatchingPackageName", cfg: dirCfg, args: []string{"./anon"}, want: `err: build constraints exclude all CUE files in ./anon: anon/anon.cue: no package name path: mod.test/test/anon@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/anon display:./anon`}, { name: "RelativeImportPathSingle", cfg: dirCfg, args: []string{"./other"}, want: `err: import failed: relative import paths not allowed ("./file"): $CWD/testdata/testmod/other/main.cue:6:2 path: mod.test/test/other@v0:main module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/other display:./other files: $CWD/testdata/testmod/other/main.cue`}, { name: "RelativePathSuccess", cfg: dirCfg, args: []string{"./hello"}, want: `path: mod.test/test/hello@v0:test module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/hello display:./hello files: $CWD/testdata/testmod/test.cue $CWD/testdata/testmod/hello/test.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { name: "ExplicitPackageIdentifier", cfg: dirCfg, args: []string{"mod.test/test/hello:test"}, want: `path: mod.test/test/hello:test module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/hello display:mod.test/test/hello:test files: $CWD/testdata/testmod/test.cue $CWD/testdata/testmod/hello/test.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { name: "NoPackageName", cfg: dirCfg, args: []string{"mod.test/test/hello:nonexist"}, want: `err: cannot find package "mod.test/test/hello": no files in package directory with package name "nonexist" path: mod.test/test/hello:nonexist module: "" root: $CWD/testdata/testmod dir: "" display:mod.test/test/hello:nonexist`, }, { name: "ExplicitNonPackageFiles", cfg: dirCfg, args: []string{"./anon.cue", "./other/anon.cue"}, want: `path: "" module: "" root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:command-line-arguments files: $CWD/testdata/testmod/anon.cue $CWD/testdata/testmod/other/anon.cue`, }, { name: "AbsoluteFileIsNormalized", // TODO(rogpeppe) what is this actually testing? cfg: dirCfg, // Absolute file is normalized. args: []string{filepath.Join(cwd, testdata("testmod", "anon.cue"))}, want: `path: "" module: "" root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:command-line-arguments files: $CWD/testdata/testmod/anon.cue`}, { name: "StandardInput", cfg: dirCfg, args: []string{"-"}, want: `path: "" module: "" root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:command-line-arguments files: -`}, { name: "BadIdentifier", cfg: dirCfg, args: []string{"foo.com/bad-identifier"}, want: `err: cannot determine package name for "foo.com/bad-identifier"; set it explicitly with ':' cannot find package "foo.com/bad-identifier": cannot find module providing package foo.com/bad-identifier path: foo.com/bad-identifier module: "" root: $CWD/testdata/testmod dir: "" display:foo.com/bad-identifier`, }, { name: "NonexistentStdlibImport", cfg: dirCfg, args: []string{"nonexisting"}, want: `err: standard library import path "nonexisting" cannot be imported as a CUE package path: nonexisting module: "" root: $CWD/testdata/testmod dir: "" display:nonexisting`, }, { name: "ExistingStdlibImport", cfg: dirCfg, args: []string{"strconv"}, want: `err: standard library import path "strconv" cannot be imported as a CUE package path: strconv module: "" root: $CWD/testdata/testmod dir: "" display:strconv`, }, { name: "EmptyPackageDirectory", cfg: dirCfg, args: []string{"./empty"}, want: `err: no CUE files in ./empty path: mod.test/test/empty@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/empty display:./empty`, }, { name: "PackageWithImports", cfg: dirCfg, args: []string{"./imports"}, want: `path: mod.test/test/imports@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/imports display:./imports files: $CWD/testdata/testmod/imports/imports.cue imports: mod.test/catch: $CWD/testdata/testmod/cue.mod/pkg/mod.test/catch/catch.cue mod.test/helper:helper1: $CWD/testdata/testmod/cue.mod/pkg/mod.test/helper/helper1.cue`}, { name: "PackageWithImportsWithSkipImportsConfig", cfg: &Config{ Dir: testdataDir, Tools: true, SkipImports: true, }, args: []string{"./imports"}, want: `path: mod.test/test/imports@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/imports display:./imports files: $CWD/testdata/testmod/imports/imports.cue`}, { name: "OnlyToolFiles", cfg: dirCfg, args: []string{"./toolonly"}, want: `path: mod.test/test/toolonly@v0:foo module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/toolonly display:./toolonly files: $CWD/testdata/testmod/toolonly/foo_tool.cue`}, { name: "OnlyToolFilesWithToolsDisabledInConfig", cfg: &Config{ Dir: testdataDir, }, args: []string{"./toolonly"}, want: `err: build constraints exclude all CUE files in ./toolonly: test.cue: package is test, want foo toolonly/foo_tool.cue: _tool.cue files excluded in non-cmd mode path: mod.test/test/toolonly@v0:foo module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/toolonly display:./toolonly`}, { name: "WithBoolTag", cfg: &Config{ Dir: testdataDir, Tags: []string{"prod"}, }, args: []string{"./tags"}, want: `path: mod.test/test/tags@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/tags display:./tags files: $CWD/testdata/testmod/tags/prod.cue`}, { name: "WithAttrValTag", cfg: &Config{ Dir: testdataDir, Tags: []string{"prod", "foo=bar"}, }, args: []string{"./tags"}, want: `path: mod.test/test/tags@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/tags display:./tags files: $CWD/testdata/testmod/tags/prod.cue`}, { name: "UnusedTag", cfg: &Config{ Dir: testdataDir, Tags: []string{"prod"}, }, args: []string{"./tagsbad"}, want: `err: tag "prod" not used in any file previous declaration here: $CWD/testdata/testmod/tagsbad/prod.cue:1:1 multiple @if attributes: $CWD/testdata/testmod/tagsbad/prod.cue:2:1 path: mod.test/test/tagsbad@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/tagsbad display:./tagsbad`}, { name: "ImportCycle", cfg: &Config{ Dir: testdataDir, }, args: []string{"./cycle"}, want: `err: import failed: import failed: import failed: package import cycle not allowed: $CWD/testdata/testmod/cycle/cycle.cue:3:8 $CWD/testdata/testmod/cue.mod/pkg/mod.test/cycle/bar/bar.cue:3:8 $CWD/testdata/testmod/cue.mod/pkg/mod.test/cycle/foo/foo.cue:3:8 path: mod.test/test/cycle@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/cycle display:./cycle files: $CWD/testdata/testmod/cycle/cycle.cue`}, { name: "AcceptLegacyModuleWithLegacyModule", cfg: &Config{ Dir: testdata("testmod_legacy"), AcceptLegacyModules: true, }, want: `path: test.example/foo@v0 module: test.example/foo@v0 root: $CWD/testdata/testmod_legacy dir: $CWD/testdata/testmod_legacy display:. files: $CWD/testdata/testmod_legacy/foo.cue`}, { name: "AcceptLegacyModuleWithNonLegacyModule", cfg: &Config{ Dir: testdataDir, Tools: true, AcceptLegacyModules: true, }, args: []string{"./imports"}, want: `path: mod.test/test/imports@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/imports display:./imports files: $CWD/testdata/testmod/imports/imports.cue imports: mod.test/catch: $CWD/testdata/testmod/cue.mod/pkg/mod.test/catch/catch.cue mod.test/helper:helper1: $CWD/testdata/testmod/cue.mod/pkg/mod.test/helper/helper1.cue`}, { name: "MismatchedModulePathInConfig", cfg: &Config{ Dir: testdataDir, Tools: true, Module: "wrong.test@v0", }, args: []string{"./imports"}, want: `err: inconsistent modules: got "mod.test/test@v0", want "wrong.test@v0" path: "" module: wrong.test@v0 root: "" dir: "" display:""`}, { name: "ModulePathInConfigWithoutMajorVersion", cfg: &Config{ Dir: testdataDir, Tools: true, Module: "mod.test/test", }, args: []string{"./imports"}, want: `err: inconsistent modules: got "mod.test/test@v0", want "mod.test/test" path: "" module: mod.test/test root: "" dir: "" display:""`}, { name: "ModulePathInConfigWithoutMajorVersionAndMismatchedPath", cfg: &Config{ Dir: testdataDir, Tools: true, Module: "mod.test/wrong", }, args: []string{"./imports"}, want: `err: inconsistent modules: got "mod.test/test@v0", want "mod.test/wrong" path: "" module: mod.test/wrong root: "" dir: "" display:""`}, { name: "ExplicitPackageWithUnqualifiedImportPath#1", cfg: &Config{ Dir: filepath.Join(testdataDir, "multi"), Package: "main", }, args: []string{"."}, want: `path: mod.test/test/multi@v0:main module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/multi display:. files: $CWD/testdata/testmod/multi/file.cue`}, { name: "ExplicitPackageWithUnqualifiedImportPath#2", // This test replicates the failure reported in https://cuelang.org/issue/3213 cfg: &Config{ Dir: filepath.Join(testdataDir, "multi2"), Package: "other", }, args: []string{"."}, want: `path: mod.test/test/multi2@v0:other module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/multi2 display:. files: $CWD/testdata/testmod/multi2/other.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { name: "ExplicitPackageWithUnqualifiedImportPath#3", cfg: &Config{ Dir: filepath.Join(testdataDir, "multi3"), Package: "other", }, args: []string{"."}, want: `path: mod.test/test/multi3@v0:other module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/multi3 display:. files: $CWD/testdata/testmod/multi3/other.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { // Test that we can explicitly ask for non-package // CUE files by setting Config.Package to "_". name: "ExplicitPackageWithUnqualifiedImportPath#4", cfg: &Config{ Dir: filepath.Join(testdataDir, "multi4"), Package: "_", }, args: []string{"."}, want: `path: mod.test/test/multi4@v0:_ module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/multi4 display:. files: $CWD/testdata/testmod/multi4/nopackage1.cue $CWD/testdata/testmod/multi4/nopackage2.cue`}, { // Test what happens when there's a single CUE file // with an explicit `package _` directive. name: "ExplicitPackageWithUnqualifiedImportPath#5", cfg: &Config{ Dir: filepath.Join(testdataDir, "multi5"), Package: "_", }, args: []string{"."}, want: `path: mod.test/test/multi5@v0:_ module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/multi5 display:. files: $CWD/testdata/testmod/multi5/nopackage.cue`}, { // Check that imports are only considered from files // that match the build paths. name: "BuildTagsWithImports#1", cfg: &Config{ Dir: filepath.Join(testdataDir, "tagswithimports"), Tags: []string{"prod"}, }, args: []string{"."}, want: `path: mod.test/test/tagswithimports@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/tagswithimports display:. files: $CWD/testdata/testmod/tagswithimports/prod.cue imports: mod.test/test/hello:test: $CWD/testdata/testmod/test.cue $CWD/testdata/testmod/hello/test.cue mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { // Check that imports are only considered from files // that match the build paths. When we don't have the prod // tag, the bad import path mentioned in testdata/testmod/tagswithimports/nonprod.cue // surfaces in the errors. name: "BuildTagsWithImports#2", cfg: &Config{ Dir: filepath.Join(testdataDir, "tagswithimports"), }, args: []string{"."}, want: `err: mod.test/test/tagswithimports@v0: import failed: cannot find package "bad-import.example/foo": cannot find module providing package bad-import.example/foo: $CWD/testdata/testmod/tagswithimports/nonprod.cue:5:8 path: mod.test/test/tagswithimports@v0 module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/tagswithimports display:. files: $CWD/testdata/testmod/tagswithimports/nonprod.cue`}, { name: "ModuleFileNonDirectory", cfg: &Config{ Dir: testdata("testmod_legacymodfile"), }, args: []string{"."}, want: `err: cue.mod files are no longer supported; use cue.mod/module.cue path: "" module: "" root: "" dir: "" display:""`}, { // This test checks that files in parent directories // do not result in irrelevant instances appearing // in the result of Instances. name: "Issue3306", cfg: &Config{ Dir: testdataDir, Package: "*", SkipImports: true, }, args: []string{"./issue3306/..."}, want: `path: mod.test/test/issue3306@v0:x module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/issue3306 display:./issue3306 files: $CWD/testdata/testmod/issue3306/x.cue path: mod.test/test/issue3306/a@v0:a module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/issue3306/a display:./issue3306/a files: $CWD/testdata/testmod/issue3306/a/a.cue path: mod.test/test/issue3306/a@v0:b module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/issue3306/a display:./issue3306/a files: $CWD/testdata/testmod/issue3306/a/b.cue path: mod.test/test/issue3306/a@v0:x module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/issue3306/a display:./issue3306/a files: $CWD/testdata/testmod/issue3306/x.cue $CWD/testdata/testmod/issue3306/a/x.cue path: mod.test/test/issue3306/x@v0:x module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/issue3306/x display:./issue3306/x files: $CWD/testdata/testmod/issue3306/x.cue $CWD/testdata/testmod/issue3306/x/x.cue`}, { // This test checks that when we use Package: "*", // we can still use imported packages. name: "AllPackagesWithImports", cfg: &Config{ Dir: testdataDir, Package: "*", }, args: []string{"."}, want: `path: mod.test/test@v0:_ module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:. files: $CWD/testdata/testmod/anon.cue path: mod.test/test@v0:test module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod display:. files: $CWD/testdata/testmod/test.cue imports: mod.test/test/sub: $CWD/testdata/testmod/sub/sub.cue`}, { // This tests that we can load a CUE package by pointing Dir to it // even when the package's directory name ends with ".cue". name: "DirWithCUEFileExtension", cfg: &Config{ Dir: filepath.Join(testdataDir, "testdir.cue"), }, args: []string{"."}, want: `path: mod.test/test/testdir.cue@v0:testdir module: mod.test/test@v0 root: $CWD/testdata/testmod dir: $CWD/testdata/testmod/testdir.cue display:. files: $CWD/testdata/testmod/testdir.cue/test.cue`, }} tdtest.Run(t, testCases, func(t *tdtest.T, tc *loadTest) { pkgs := Instances(tc.args, tc.cfg) buf := &bytes.Buffer{} err := pkgInfo.Execute(buf, pkgs) if err != nil { t.Fatal(err) } got := strings.TrimSpace(buf.String()) got = strings.Replace(got, cwd, "$CWD", -1) // Errors are printed with slashes, so replace // the slash-separated form of CWD too. got = strings.Replace(got, filepath.ToSlash(cwd), "$CWD", -1) // Make test work with Windows. got = strings.Replace(got, string(filepath.Separator), "/", -1) t.Equal(got, tc.want) }) } var pkgInfo = template.Must(template.New("pkg").Funcs(template.FuncMap{ "errordetails": func(err error) string { s := errors.Details(err, &errors.Config{ ToSlash: true, }) s = strings.TrimSuffix(s, "\n") return s }}).Parse(` {{- range . -}} {{- if .Err}}err: {{errordetails .Err}}{{end}} path: {{if .ImportPath}}{{.ImportPath}}{{else}}""{{end}} module: {{with .Module}}{{.}}{{else}}""{{end}} root: {{with .Root}}{{.}}{{else}}""{{end}} dir: {{with .Dir}}{{.}}{{else}}""{{end}} display:{{with .DisplayPath}}{{.}}{{else}}""{{end}} {{if .Files -}} files: {{- range .Files}} {{.Filename}} {{- end -}} {{- end}} {{if .Imports -}} imports: {{- range .Dependencies}} {{.ImportPath}}:{{range .Files}} {{.Filename}}{{end}} {{- end}} {{end -}} {{- end -}} `)) func TestOverlays(t *testing.T) { cwd, _ := os.Getwd() abs := func(path string) string { return filepath.Join(cwd, path) } c := &Config{ Overlay: map[string]Source{ // Not necessary, but nice to add. abs("cue.mod/module.cue"): FromString(`module: "mod.test", language: version: "v0.9.0"`), abs("dir/top.cue"): FromBytes([]byte(` package top msg: "Hello" `)), abs("dir/b/foo.cue"): FromString(` package foo a: <= 5 `), abs("dir/b/bar.cue"): FromString(` package foo a: >= 5 `), }, } want := []string{ `{msg:"Hello"}`, `{a:5}`, } rmSpace := func(r rune) rune { if unicode.IsSpace(r) { return -1 } return r } ctx := cuecontext.New() insts, err := ctx.BuildInstances(Instances([]string{"./dir/..."}, c)) if err != nil { t.Fatal(err) } for i, inst := range insts { if err := inst.Err(); err != nil { t.Error(err) continue } b, err := format.Node(inst.Value().Syntax(cue.Final())) if err != nil { t.Error(err) continue } if got := string(bytes.Map(rmSpace, b)); got != want[i] { t.Errorf("%s: got %s; want %s", inst.BuildInstance().Dir, got, want[i]) } } } func TestLoadOrder(t *testing.T) { testDir := t.TempDir() letters := "abcdefghij" for _, c := range letters { contents := fmt.Sprintf(` package %s x: 1 `, string(c)) err := os.WriteFile(filepath.Join(testDir, string(c)+".cue"), []byte(contents), 0o666) qt.Assert(t, qt.IsNil(err)) } insts := Instances([]string{"."}, &Config{ Package: "*", Dir: testDir, }) var actualFiles = []string{} for _, inst := range insts { for _, f := range inst.BuildFiles { if strings.Contains(f.Filename, testDir) { actualFiles = append(actualFiles, filepath.Base(f.Filename)) } } } var expectedFiles []string for _, c := range letters { expectedFiles = append(expectedFiles, string(c)+".cue") } qt.Assert(t, qt.DeepEquals(actualFiles, expectedFiles)) } func TestLoadInstancesConcurrent(t *testing.T) { // This test is designed to fail when run with the race detector // if there's an underlying race condition. // See https://cuelang.org/issue/1746 race(t, func() error { _, err := getInst(".", testdata("testmod", "hello")) return err }) } func race(t *testing.T, f func() error) { var wg sync.WaitGroup for i := 0; i < 2; i++ { wg.Add(1) go func() { if err := f(); err != nil { t.Error(err) } wg.Done() }() } wg.Wait() } cue-lang-cue-db9cc73/cue/load/module_test.go000066400000000000000000000066521474664451600210570ustar00rootroot00000000000000package load_test import ( "fmt" "io/fs" "os" "path/filepath" "strings" "testing" "github.com/go-quicktest/qt" "golang.org/x/tools/txtar" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/load" "cuelang.org/go/internal/cuetxtar" "cuelang.org/go/internal/registrytest" "cuelang.org/go/mod/modcache" ) func TestModuleLoadWithInvalidRegistryConfig(t *testing.T) { // When there's an invalid registry configuration, // we shouldn't get an error unless the module actually tries to use a registry. t.Setenv("CUE_REGISTRY", "invalid}host:") cacheDir := t.TempDir() t.Setenv("CUE_CACHE_DIR", cacheDir) insts := load.Instances([]string{"./imports"}, &load.Config{ Dir: filepath.Join("testdata", "testmod"), }) qt.Assert(t, qt.IsNil(insts[0].Err)) // Check that nothing has been created in the cache directory (no // side-effects). entries, err := os.ReadDir(cacheDir) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.HasLen(entries, 0)) // Now check that we do get an error when we try to use a module // that requires module resolution. testData, err := os.ReadFile(filepath.Join("testdata", "testfetch", "simple.txtar")) qt.Assert(t, qt.IsNil(err)) cfg := &load.Config{ Dir: t.TempDir(), Overlay: map[string]load.Source{}, } a := txtar.Parse(testData) for _, f := range a.Files { if !strings.HasPrefix(f.Name, "_registry/") { cfg.Overlay[filepath.Join(cfg.Dir, f.Name)] = load.FromBytes(f.Data) } } insts = load.Instances([]string{"."}, cfg) qt.Assert(t, qt.ErrorMatches(insts[0].Err, `import failed: .*main.cue:2:8: cannot find package "example.com@v0": cannot fetch example.com@v0.0.1: bad value for \$CUE_REGISTRY: invalid registry "invalid}host:": invalid host name "invalid}host:" in registry`)) // Try again with environment variables passed in Env. // This is really just a smoke test to make sure that Env is // passed through to the underlying modconfig call. cfg.Env = []string{ "CUE_REGISTRY=invalid}host2:", "CUE_CACHE_DIR=" + cacheDir, } insts = load.Instances([]string{"."}, cfg) qt.Assert(t, qt.ErrorMatches(insts[0].Err, `import failed: .*main.cue:2:8: cannot find package "example.com@v0": cannot fetch example.com@v0.0.1: bad value for \$CUE_REGISTRY: invalid registry "invalid}host2:": invalid host name "invalid}host2:" in registry`)) } func TestModuleFetch(t *testing.T) { test := cuetxtar.TxTarTest{ Root: "./testdata/testfetch", Name: "modfetch", } test.Run(t, func(t *cuetxtar.Test) { tfs, err := txtar.FS(t.Archive) qt.Assert(t, qt.IsNil(err)) rfs, err := fs.Sub(tfs, "_registry") qt.Assert(t, qt.IsNil(err)) r, err := registrytest.New(rfs, "") qt.Assert(t, qt.IsNil(err)) defer r.Close() tmpDir := t.TempDir() t.LoadConfig.Env = []string{ "CUE_CACHE_DIR=" + filepath.Join(tmpDir, "cache"), "CUE_REGISTRY=" + r.Host() + "+insecure", "CUE_CONFIG_DIR=" + filepath.Join(tmpDir, "config"), } // The fetched files are read-only, so testing fails when trying // to remove them. defer modcache.RemoveAll(tmpDir) ctx := cuecontext.New() insts := t.RawInstances() if len(insts) != 1 { t.Fatalf("wrong instance count; got %d want 1", len(insts)) } inst := insts[0] if inst.Err != nil { errors.Print(t.Writer("error"), inst.Err, &errors.Config{ ToSlash: true, Cwd: t.Dir, }) return } v := ctx.BuildInstance(inst) if err := v.Validate(); err != nil { t.Fatal(err) } fmt.Fprintf(t, "%v\n", v) }) } cue-lang-cue-db9cc73/cue/load/package.go000066400000000000000000000022311474664451600201130ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load // Package rules: // // - the package clause defines a namespace. // - a cue file without a package clause is a standalone file. // - all files with the same package name within a directory and its // ancestor directories up to the package root belong to the same package. // - The package root is either the top of the file hierarchy or the first // directory in which a cue.mod file is defined. // // The contents of a namespace depends on the directory that is selected as the // starting point to load a package. An instance defines a package-directory // pair. cue-lang-cue-db9cc73/cue/load/search.go000066400000000000000000000463771474664451600200100ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "fmt" "io/fs" "path" "path/filepath" "strings" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/mod/modimports" "cuelang.org/go/mod/module" ) // A match represents the result of matching a single package pattern. type match struct { Pattern string // the pattern itself Literal bool // whether it is a literal (no wildcards) Pkgs []*build.Instance Err errors.Error } // TODO: should be matched from module file only. // The pattern is either "all" (all packages), "std" (standard packages), // "cmd" (standard commands), or a path including "...". func (l *loader) matchPackages(pattern, pkgName string) *match { // cfg := l.cfg m := &match{ Pattern: pattern, Literal: false, } // match := func(string) bool { return true } // treeCanMatch := func(string) bool { return true } // if !isMetaPackage(pattern) { // match = matchPattern(pattern) // treeCanMatch = treeCanMatchPattern(pattern) // } // have := map[string]bool{ // "builtin": true, // ignore pseudo-package that exists only for documentation // } // for _, src := range cfg.srcDirs() { // if pattern == "std" || pattern == "cmd" { // continue // } // src = filepath.Clean(src) + string(filepath.Separator) // root := src // if pattern == "cmd" { // root += "cmd" + string(filepath.Separator) // } // filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { // if err != nil || path == src { // return nil // } // want := true // // Avoid .foo, _foo, and testdata directory trees. // _, elem := filepath.Split(path) // if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { // want = false // } // name := filepath.ToSlash(path[len(src):]) // if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { // // The name "std" is only the standard library. // // If the name is cmd, it's the root of the command tree. // want = false // } // if !treeCanMatch(name) { // want = false // } // if !fi.IsDir() { // if fi.Mode()&os.ModeSymlink != 0 && want { // if target, err := os.Stat(path); err == nil && target.IsDir() { // fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) // } // } // return nil // } // if !want { // return skipDir // } // if have[name] { // return nil // } // have[name] = true // if !match(name) { // return nil // } // pkg := l.importPkg(".", path) // if err := pkg.Error; err != nil { // if _, noGo := err.(*noCUEError); noGo { // return nil // } // } // // If we are expanding "cmd", skip main // // packages under cmd/vendor. At least as of // // March, 2017, there is one there for the // // vendored pprof tool. // if pattern == "cmd" && strings.HasPrefix(pkg.DisplayPath, "cmd/vendor") && pkg.PkgName == "main" { // return nil // } // m.Pkgs = append(m.Pkgs, pkg) // return nil // }) // } return m } // matchPackagesInFS is like allPackages but is passed a pattern // beginning ./ or ../, meaning it should scan the tree rooted // at the given directory. There are ... in the pattern too. // (See cue help inputs for pattern syntax.) func (l *loader) matchPackagesInFS(pattern, pkgName string) *match { c := l.cfg m := &match{ Pattern: pattern, Literal: false, } // Find directory to begin the scan. // Could be smarter but this one optimization // is enough for now, since ... is usually at the // end of a path. i := strings.Index(pattern, "...") dir, _ := path.Split(pattern[:i]) root := l.abs(dir) // Find new module root from here or check there are no additional // cue.mod files between here and the next module. if !hasFilepathPrefix(root, c.ModuleRoot) { m.Err = errors.Newf(token.NoPos, "cue: pattern %s refers to dir %s, outside module root %s", pattern, root, c.ModuleRoot) return m } pkgDir := filepath.Join(root, modDir) _ = c.fileSystem.walk(root, func(path string, entry fs.DirEntry, err errors.Error) errors.Error { if err != nil || !entry.IsDir() { return nil } if path == pkgDir { return skipDir } top := path == root // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". _, elem := filepath.Split(path) dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." if dot || strings.HasPrefix(elem, "_") || (elem == "testdata" && !top) { return skipDir } if !top { // Ignore other modules found in subdirectories. if _, err := c.fileSystem.stat(filepath.Join(path, modDir)); err == nil { return skipDir } } // name := prefix + filepath.ToSlash(path) // if !match(name) { // return nil // } // We keep the directory if we can import it, or if we can't import it // due to invalid CUE source files. This means that directories // containing parse errors will be built (and fail) instead of being // silently skipped as not matching the pattern. // Do not take root, as we want to stay relative // to one dir only. relPath, err2 := filepath.Rel(c.Dir, path) if err2 != nil { panic(err2) // Should never happen because c.Dir is absolute. } relPath = "./" + filepath.ToSlash(relPath) // TODO: consider not doing these checks here. inst := l.newRelInstance(token.NoPos, relPath, pkgName) pkgs := l.importPkg(token.NoPos, inst) for _, p := range pkgs { if err := p.Err; err != nil && (p == nil || len(p.InvalidFiles) == 0) { switch err.(type) { case *NoFilesError: if c.DataFiles && len(p.OrphanedFiles) > 0 { break } return nil default: m.Err = errors.Append(m.Err, err) } } } m.Pkgs = append(m.Pkgs, pkgs...) return nil }) return m } // importPaths returns the matching paths to use for the given command line. // It calls ImportPathsQuiet and then WarnUnmatched. func (l *loader) importPaths(patterns []string) []*match { matches := l.importPathsQuiet(patterns) warnUnmatched(matches) return matches } // importPathsQuiet is like importPaths but does not warn about patterns with no matches. func (l *loader) importPathsQuiet(patterns []string) []*match { var out []*match for _, a := range cleanPatterns(patterns) { if isMetaPackage(a) { out = append(out, l.matchPackages(a, l.cfg.Package)) continue } orig := a pkgName := l.cfg.Package switch p := strings.IndexByte(a, ':'); { case p < 0: case p == 0: pkgName = a[1:] a = "." default: pkgName = a[p+1:] a = a[:p] } if pkgName == "*" { pkgName = "" } if strings.Contains(a, "...") { if isLocalImport(a) { out = append(out, l.matchPackagesInFS(a, pkgName)) } else { out = append(out, l.matchPackages(a, pkgName)) } continue } var p *build.Instance if isLocalImport(a) { p = l.newRelInstance(token.NoPos, a, pkgName) } else { p = l.newInstance(token.NoPos, importPath(orig)) } pkgs := l.importPkg(token.NoPos, p) out = append(out, &match{Pattern: a, Literal: true, Pkgs: pkgs}) } return out } type resolvedPackageArg struct { // The original field may be needed once we want to replace the original // package pattern matching code, as it is necessary to populate Instance.DisplayPath. original string resolvedCanonical string } func expandPackageArgs(c *Config, pkgArgs []string, pkgQual string, tg *tagger) ([]resolvedPackageArg, error) { expanded := make([]resolvedPackageArg, 0, len(pkgArgs)) for _, p := range pkgArgs { var err error expanded, err = appendExpandedPackageArg(c, expanded, p, pkgQual, tg) if err != nil { return nil, err } } return expanded, nil } // appendExpandedPackageArg appends all the package paths matched by p to pkgPaths // and returns the result. It also cleans the paths and makes them absolute. // // pkgQual is used to determine which packages to match when wildcards are expanded. // Its semantics follow those of [Config.Package]. func appendExpandedPackageArg(c *Config, pkgPaths []resolvedPackageArg, p string, pkgQual string, tg *tagger) ([]resolvedPackageArg, error) { origp := p if filepath.IsAbs(p) { return nil, fmt.Errorf("cannot use absolute directory %q as package path", p) } // Arguments are supposed to be import paths, but // as a courtesy to Windows developers, rewrite \ to / // in command-line arguments. Handles .\... and so on. p = filepath.ToSlash(p) ip := module.ParseImportPath(p) if ip.Qualifier == "_" { return nil, fmt.Errorf("invalid import path qualifier _ in %q", origp) } isRel := strings.HasPrefix(ip.Path, "./") // Put argument in canonical form. ip.Path = path.Clean(ip.Path) if isRel && ip.Path != "." { // Preserve leading "./". ip.Path = "./" + ip.Path } isLocal := isLocalImport(ip.Path) // Note that when c.Module is empty, c.ModuleRoot is sometimes, // but not always, the same as c.Dir. Specifically it might point // to the directory containing a cue.mod directory even if that // directory doesn't actually contain a module.cue file. moduleRoot := c.ModuleRoot if isLocal { if c.Module != "" { // Make local import paths into absolute paths inside // the module root. absPath := path.Join(c.Dir, ip.Path) pkgPath, err := importPathFromAbsDir(c, absPath, origp) if err != nil { return nil, err } ip1 := module.ParseImportPath(string(pkgPath)) // Leave ip.Qualifier and ip.ExplicitQualifier intact. ip.Path = ip1.Path ip.Version = ip1.Version } else { // There's no module, so we can't make // the import path absolute. moduleRoot = c.Dir } } if !strings.Contains(ip.Path, "...") { if isLocal && !ip.ExplicitQualifier { // A package qualifier has not been explicitly specified for a local // import path so we need to walk the package directory to find the // packages in it. We have a special rule for local imports because it's // inconvenient always to have to specify a package qualifier when // there's only one package in the current directory but the last // component of its package path does not match its name. return appendExpandedUnqualifiedPackagePath(pkgPaths, origp, ip, pkgQual, module.SourceLoc{ FS: c.fileSystem.ioFS(moduleRoot), Dir: ".", }, c.Module, tg) } return append(pkgPaths, resolvedPackageArg{origp, ip.Canonical().String()}), nil } // Strip the module prefix, leaving only the directory relative // to the module root. ip, ok := cutModulePrefix(ip, c.Module) if !ok { return nil, fmt.Errorf("pattern not allowed in external package path %q", origp) } return appendExpandedWildcardPackagePath(pkgPaths, ip, pkgQual, module.SourceLoc{ FS: c.fileSystem.ioFS(moduleRoot), Dir: ".", }, c.Module, tg) } // appendExpandedUnqualifiedPackagePath expands the given import path, // which is relative to the root of the module, into its resolved and // qualified package paths according to the following rules (the first rule // that applies is used) // // 1. if pkgQual is "*", it chooses all the packages present in the // package directory. // 2. if pkgQual is "_", it looks for a package file with no package name. // 3. if there's a package named after ip.Qualifier it chooses that // 4. if there's exactly one package in the directory it will choose that. // 5. if there's more than one package in the directory, it returns a MultiplePackageError. // 6. if there are no package files in the directory, it just appends the import path as is, leaving it // to later logic to produce an error in this case. func appendExpandedUnqualifiedPackagePath(pkgPaths []resolvedPackageArg, origp string, ip module.ImportPath, pkgQual string, mainModRoot module.SourceLoc, mainModPath string, tg *tagger) (_ []resolvedPackageArg, _err error) { ipRel, ok := cutModulePrefix(ip, mainModPath) if !ok { // Should never happen. return nil, fmt.Errorf("internal error: local import path %q in module %q has resulted in non-internal package %q", origp, mainModPath, ip) } dir := path.Join(mainModRoot.Dir, ipRel.Path) info, err := fs.Stat(mainModRoot.FS, dir) if err != nil { // The package directory doesn't exist. // Treat it like an empty directory and let later logic deal with it. return append(pkgPaths, resolvedPackageArg{origp, ip.String()}), nil } if !info.IsDir() { return nil, fmt.Errorf("%s is a file and not a package directory", origp) } iter := modimports.PackageFiles(mainModRoot.FS, dir, "*") // 1. if pkgQual is "*", it appends all the packages present in the package directory. if pkgQual == "*" { wasAdded := make(map[string]bool) iter(func(f modimports.ModuleFile, err error) bool { if err != nil { _err = err return false } if err := shouldBuildFile(f.Syntax, tg.tagIsSet); err != nil { // Later build logic should pick up and report the same error. return true } pkgName := f.Syntax.PackageName() if wasAdded[pkgName] { return true } wasAdded[pkgName] = true ip := ip ip.Qualifier = pkgName p := ip.String() pkgPaths = append(pkgPaths, resolvedPackageArg{p, p}) return true }) if _err != nil { return nil, _err } return pkgPaths, nil } var files []modimports.ModuleFile foundQualifier := false // TODO(rog): for f, err := range iter { iter(func(f modimports.ModuleFile, err error) bool { if err != nil { _err = err return false } pkgName := f.Syntax.PackageName() // 2. if pkgQual is "_", it looks for a package file with no package name. // 3. if there's a package named after ip.Qualifier it chooses that if (pkgName != "" && pkgName == ip.Qualifier) || (pkgQual == "_" && pkgName == "") { foundQualifier = true return false } if pkgName != "" { files = append(files, f) } return true }) if _err != nil { return nil, _err } if foundQualifier { // We found the actual package that was implied by the import path (or pkgQual == "_"). // This takes precedence over anything else. return append(pkgPaths, resolvedPackageArg{origp, ip.String()}), nil } if len(files) == 0 { // 6. if there are no package files in the directory, it just appends the import path as is, // leaving it to later logic to produce an error in this case. return append(pkgPaths, resolvedPackageArg{origp, ip.String()}), nil } pkgName := files[0].Syntax.PackageName() for _, f := range files[1:] { // 5. if there's more than one package in the directory, it returns a MultiplePackageError. if pkgName1 := f.Syntax.PackageName(); pkgName1 != pkgName { return nil, &MultiplePackageError{ Dir: dir, Packages: []string{pkgName, pkgName1}, Files: []string{ path.Base(files[0].FilePath), path.Base(f.FilePath), }, } } } // 4. if there's exactly one package in the directory it will choose that. ip.Qualifier = pkgName return append(pkgPaths, resolvedPackageArg{origp, ip.String()}), nil } // appendExpandedWildcardPackagePath expands the given pattern into any packages that it matches // and appends the results to pkgPaths. It returns an error if the pattern matches nothing. // // Note: // * We know that pattern contains "..." // * We know that pattern is relative to the module root func appendExpandedWildcardPackagePath(pkgPaths []resolvedPackageArg, pattern module.ImportPath, pkgQual string, mainModRoot module.SourceLoc, mainModPath string, tg *tagger) (_ []resolvedPackageArg, _err error) { modIpath := module.ParseImportPath(mainModPath) // Find directory to begin the scan. // Could be smarter but this one optimization is enough for now, // since ... is usually at the end of a path. // TODO: strip package qualifier. i := strings.Index(pattern.Path, "...") dir, _ := path.Split(pattern.Path[:i]) dir = path.Join(mainModRoot.Dir, dir) var isSelected func(string) bool switch pkgQual { case "_": isSelected = func(pkgName string) bool { return pkgName == "" } case "*": isSelected = func(pkgName string) bool { return true } case "": isSelected = func(pkgName string) bool { // The package ambiguity logic will be triggered if there's more than one // package in the same directory. return pkgName != "" } default: isSelected = func(pkgName string) bool { return pkgName == pkgQual } } var prevFile modimports.ModuleFile var prevImportPath module.ImportPath iter := modimports.AllModuleFiles(mainModRoot.FS, dir) iter(func(f modimports.ModuleFile, err error) bool { if err != nil { return false } if err := shouldBuildFile(f.Syntax, tg.tagIsSet); err != nil { // Later build logic should pick up and report the same error. return true } pkgName := f.Syntax.PackageName() if !isSelected(pkgName) { return true } if pkgName == "" { pkgName = "_" } ip := module.ImportPath{ Path: path.Join(modIpath.Path, path.Dir(f.FilePath)), Qualifier: pkgName, Version: modIpath.Version, } if modIpath.Path == "" { // There's no module, so make sure that the path still looks like a relative import path. if !strings.HasPrefix(ip.Path, "../") { ip.Path = "./" + ip.Path } } if ip == prevImportPath { // TODO(rog): this isn't sufficient for full deduplication: we can get an alternation of different // package names within the same directory. We'll need to maintain a map. return true } if pkgQual == "" { // Note: we can look at the previous item only rather than maintaining a map // because modimports.AllModuleFiles guarantees that files in the same // package are always adjacent. if prevFile.FilePath != "" && prevImportPath.Path == ip.Path && ip.Qualifier != prevImportPath.Qualifier { // A wildcard isn't currently allowed to match multiple packages // in a single directory. _err = &MultiplePackageError{ Dir: path.Dir(f.FilePath), Packages: []string{prevImportPath.Qualifier, ip.Qualifier}, Files: []string{ path.Base(prevFile.FilePath), path.Base(f.FilePath), }, } return false } } pkgPaths = append(pkgPaths, resolvedPackageArg{ip.String(), ip.String()}) prevFile, prevImportPath = f, ip return true }) return pkgPaths, _err } // cutModulePrefix strips the given module path from p and reports whether p is inside mod. // It returns a relative package path within m. // // If p does not contain a major version suffix but otherwise matches mod, it counts as a match. func cutModulePrefix(p module.ImportPath, mod string) (module.ImportPath, bool) { if mod == "" { return p, true } modPath, modVers, ok := module.SplitPathVersion(mod) if !ok { modPath = mod } if !strings.HasPrefix(p.Path, modPath) { return module.ImportPath{}, false } if p.Path == modPath { p.Path = "." return p, true } if p.Path[len(modPath)] != '/' { return module.ImportPath{}, false } if p.Version != "" && modVers != "" && p.Version != modVers { return module.ImportPath{}, false } p.Path = "." + p.Path[len(modPath):] p.Version = "" return p, true } cue-lang-cue-db9cc73/cue/load/source.go000066400000000000000000000032371474664451600200270ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "cuelang.org/go/cue/ast" "cuelang.org/go/cue/format" ) // A Source represents file contents. type Source interface { contents() ([]byte, *ast.File, error) } // FromString creates a Source from the given string. func FromString(s string) Source { return stringSource(s) } // FromBytes creates a Source from the given bytes. The contents are not // copied and should not be modified. func FromBytes(b []byte) Source { return bytesSource(b) } // FromFile creates a Source from the given *ast.File. The file should not be // modified. It is assumed the file is error-free. func FromFile(f *ast.File) Source { return (*fileSource)(f) } type stringSource string func (s stringSource) contents() ([]byte, *ast.File, error) { return []byte(s), nil, nil } type bytesSource []byte func (s bytesSource) contents() ([]byte, *ast.File, error) { return []byte(s), nil, nil } type fileSource ast.File func (s *fileSource) contents() ([]byte, *ast.File, error) { f := (*ast.File)(s) // TODO: wasteful formatting, but needed for now. b, err := format.Node(f) return b, f, err } cue-lang-cue-db9cc73/cue/load/tags.go000066400000000000000000000215621474664451600174660ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "crypto/rand" "encoding/hex" "os" "os/user" "runtime" "strings" "sync" "time" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/buildattr" "cuelang.org/go/internal/cli" ) type tagger struct { cfg *Config // tagMap holds true for all the tags in cfg.Tags that // are not associated with a value. tagMap map[string]bool // tags keeps a record of all the @tag attibutes found in files. tags []*tag // tags found in files replacements map[ast.Node]ast.Node // mu guards the usedTags map. mu sync.Mutex // usedTags keeps a record of all the tag attributes found in files. usedTags map[string]bool } func newTagger(c *Config) *tagger { tagMap := map[string]bool{} for _, t := range c.Tags { if !strings.ContainsRune(t, '=') { tagMap[t] = true } } return &tagger{ cfg: c, tagMap: tagMap, usedTags: make(map[string]bool), } } // tagIsSet reports whether the tag with the given key // is enabled. It also updates t.usedTags to // reflect that the tag has been seen. func (tg *tagger) tagIsSet(key string) bool { tg.mu.Lock() tg.usedTags[key] = true tg.mu.Unlock() return tg.tagMap[key] } // A TagVar represents an injection variable. type TagVar struct { // Func returns an ast for a tag variable. It is only called once // per evaluation of a configuration. Func func() (ast.Expr, error) // Description documents this TagVar. Description string } const rfc3339 = "2006-01-02T15:04:05.999999999Z" // DefaultTagVars creates a new map with a set of supported injection variables. func DefaultTagVars() map[string]TagVar { return map[string]TagVar{ "now": { Func: func() (ast.Expr, error) { return ast.NewString(time.Now().UTC().Format(rfc3339)), nil }, }, "os": { Func: func() (ast.Expr, error) { return ast.NewString(runtime.GOOS), nil }, }, "arch": { Func: func() (ast.Expr, error) { return ast.NewString(runtime.GOARCH), nil }, }, "cwd": { Func: func() (ast.Expr, error) { return varToString(os.Getwd()) }, }, "username": { Func: func() (ast.Expr, error) { u, err := user.Current() if err != nil { return nil, err } return ast.NewString(u.Username), nil }, }, "hostname": { Func: func() (ast.Expr, error) { return varToString(os.Hostname()) }, }, "rand": { Func: func() (ast.Expr, error) { var b [16]byte _, err := rand.Read(b[:]) if err != nil { return nil, err } var hx [34]byte hx[0] = '0' hx[1] = 'x' hex.Encode(hx[2:], b[:]) return ast.NewLit(token.INT, string(hx[:])), nil }, }, } } func varToString(s string, err error) (ast.Expr, error) { if err != nil { return nil, err } x := ast.NewString(s) return x, nil } // A tag binds an identifier to a field to allow passing command-line values. // // A tag is of the form // // @tag(,[type=(string|int|number|bool)][,short=+]) // // The name is mandatory and type defaults to string. Tags are set using the -t // option on the command line. -t name=value will parse value for the type // defined for name and set the field for which this tag was defined to this // value. A tag may be associated with multiple fields. // // Tags also allow shorthands. If a shorthand bar is declared for a tag with // name foo, then -t bar is identical to -t foo=bar. // // It is a deliberate choice to not allow other values to be associated with // shorthands than the shorthand name itself. Doing so would create a powerful // mechanism that would assign different values to different fields based on the // same shorthand, duplicating functionality that is already available in CUE. type tag struct { key string kind cue.Kind shorthands []string vars string // -T flag hasReplacement bool field *ast.Field } func parseTag(pos token.Pos, body string) (t *tag, err errors.Error) { t = &tag{} t.kind = cue.StringKind a := internal.ParseAttrBody(pos, body) t.key, _ = a.String(0) if !ast.IsValidIdent(t.key) { return t, errors.Newf(pos, "invalid identifier %q", t.key) } if s, ok, _ := a.Lookup(1, "type"); ok { switch s { case "string": case "int": t.kind = cue.IntKind case "number": t.kind = cue.NumberKind case "bool": t.kind = cue.BoolKind default: return t, errors.Newf(pos, "invalid type %q", s) } } if s, ok, _ := a.Lookup(1, "short"); ok { for _, s := range strings.Split(s, "|") { if !ast.IsValidIdent(t.key) { return t, errors.Newf(pos, "invalid identifier %q", s) } t.shorthands = append(t.shorthands, s) } } if s, ok, _ := a.Lookup(1, "var"); ok { t.vars = s } return t, nil } func (t *tag) inject(value string, tg *tagger) errors.Error { e, err := cli.ParseValue(token.NoPos, t.key, value, t.kind) t.injectValue(e, tg) return err } func (t *tag) injectValue(x ast.Expr, tg *tagger) { injected := ast.NewBinExpr(token.AND, t.field.Value, x) if tg.replacements == nil { tg.replacements = make(map[ast.Node]ast.Node) } tg.replacements[t.field.Value] = injected t.field.Value = injected t.hasReplacement = true } // findTags defines which fields may be associated with tags. // // TODO: should we limit the depth at which tags may occur? func findTags(b *build.Instance) (tags []*tag, errs errors.Error) { findInvalidTags := func(x ast.Node, msg string) { ast.Walk(x, nil, func(n ast.Node) { if f, ok := n.(*ast.Field); ok { for _, a := range f.Attrs { if key, _ := a.Split(); key == "tag" { errs = errors.Append(errs, errors.Newf(a.Pos(), "%s", msg)) // TODO: add position of x. } } } }) } for _, f := range b.Files { ast.Walk(f, func(n ast.Node) bool { switch x := n.(type) { case *ast.ListLit: findInvalidTags(n, "@tag not allowed within lists") return false case *ast.Comprehension: findInvalidTags(n, "@tag not allowed within comprehension") return false case *ast.Field: // TODO: allow optional fields? _, _, err := ast.LabelName(x.Label) _, ok := internal.ConstraintToken(x) if err != nil || ok { findInvalidTags(n, "@tag not allowed within field constraint") return false } for _, a := range x.Attrs { key, body := a.Split() if key != "tag" { continue } t, err := parseTag(a.Pos(), body) if err != nil { errs = errors.Append(errs, err) continue } t.field = x tags = append(tags, t) } } return true }, nil) } return tags, errs } func (tg *tagger) injectTags(tags []string) errors.Error { // Parses command line args for _, s := range tags { p := strings.Index(s, "=") found := tg.usedTags[s] if p > 0 { // key-value for _, t := range tg.tags { if t.key == s[:p] { found = true if err := t.inject(s[p+1:], tg); err != nil { return err } } } if !found { return errors.Newf(token.NoPos, "no tag for %q", s[:p]) } } else { // shorthand for _, t := range tg.tags { for _, sh := range t.shorthands { if sh == s { found = true if err := t.inject(s, tg); err != nil { return err } } } } if !found { return errors.Newf(token.NoPos, "tag %q not used in any file", s) } } } if tg.cfg.TagVars != nil { vars := map[string]ast.Expr{} // Inject tag variables if the tag wasn't already set. for _, t := range tg.tags { if t.hasReplacement || t.vars == "" { continue } x, ok := vars[t.vars] if !ok { tv, ok := tg.cfg.TagVars[t.vars] if !ok { return errors.Newf(token.NoPos, "tag variable '%s' not found", t.vars) } tag, err := tv.Func() if err != nil { return errors.Wrapf(err, token.NoPos, "error getting tag variable '%s'", t.vars) } x = tag vars[t.vars] = tag } if x != nil { t.injectValue(x, tg) } } } return nil } func shouldBuildFile(f *ast.File, tagIsSet func(key string) bool) errors.Error { ok, attr, err := buildattr.ShouldBuildFile(f, tagIsSet) if err != nil { return err } if ok { return nil } if key, body := attr.Split(); key == "if" { return excludeError{errors.Newf(attr.Pos(), "@if(%s) did not match", body)} } else { return excludeError{errors.Newf(attr.Pos(), "@ignore() attribute found")} } } cue-lang-cue-db9cc73/cue/load/tags_test.go000066400000000000000000000056351474664451600205300ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package load import ( "bytes" "path/filepath" "testing" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/token" "cuelang.org/go/internal/diff" ) var testTagVars = map[string]TagVar{ "now": stringVar("2006-01-02T15:04:05.999999999Z"), "os": stringVar("m1"), "cwd": stringVar("home"), "username": stringVar("cueser"), "hostname": stringVar("cuebe"), "rand": {Func: func() (ast.Expr, error) { return ast.NewLit(token.INT, "112950970371208119678246559335704039641"), nil }}, } func stringVar(s string) TagVar { return TagVar{Func: func() (ast.Expr, error) { return ast.NewString(s), nil }} } func TestTags(t *testing.T) { dir := t.TempDir() testCases := []struct { in string out string err string }{{ in: ` rand: int @tag(foo,var=rand) time: string @tag(bar,var=now) host: string @tag(bar,var=hostname) user: string @tag(bar,var=username) cwd: string @tag(bar,var=cwd) `, out: `{ rand: 112950970371208119678246559335704039641 time: "2006-01-02T15:04:05.999999999Z" host: "cuebe" user: "cueser" cwd: "home" }`, }, { in: ` time: int @tag(bar,var=now) `, err: `time: conflicting values int and "2006-01-02T15:04:05.999999999Z" (mismatched types int and string)`, }, { // Auto inject only on marked places // TODO: Is this the right thing to do? in: ` u1: string @tag(bar,var=username) u2: string @tag(bar) `, out: `{ u1: "cueser" u2: string // not filled }`, }, { in: ` u1: string @tag(bar,var=user) `, err: `tag variable 'user' not found`, }} for _, tc := range testCases { t.Run("", func(t *testing.T) { cfg := &Config{ Dir: dir, Overlay: map[string]Source{ filepath.Join(dir, "foo.cue"): FromString(tc.in), }, TagVars: testTagVars, } b := Instances([]string{"foo.cue"}, cfg)[0] c := cuecontext.New() got := c.BuildInstance(b) switch err := got.Err(); { case (err == nil) != (tc.err == ""): t.Fatalf("error: got %v; want %v", err, tc.err) case err != nil: got := err.Error() if got != tc.err { t.Fatalf("error: got %v; want %v", got, tc.err) } default: want := c.CompileString(tc.out) if !got.Equals(want) { _, es := diff.Diff(got, want) b := &bytes.Buffer{} diff.Print(b, es) t.Error(b) } } }) } } cue-lang-cue-db9cc73/cue/load/testdata/000077500000000000000000000000001474664451600200045ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/badmod/000077500000000000000000000000001474664451600212325ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/badmod/cue.mod/000077500000000000000000000000001474664451600225645ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/badmod/cue.mod/module.cue000066400000000000000000000000511474664451600245430ustar00rootroot00000000000000 module: 123 language: version: "v0.9.0" cue-lang-cue-db9cc73/cue/load/testdata/testfetch/000077500000000000000000000000001474664451600217755ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testfetch/depnotfound.txtar000066400000000000000000000005251474664451600254100ustar00rootroot00000000000000-- out/modfetch/error -- import failed: cannot find package "example.com": cannot fetch example.com@v0.0.1: module example.com@v0.0.1: module not found: ./main.cue:2:8 -- cue.mod/module.cue -- module: "main.org@v0" language: version: "v0.8.0" deps: "example.com@v0": v: "v0.0.1" -- main.cue -- package main import _ "example.com:main" cue-lang-cue-db9cc73/cue/load/testdata/testfetch/nodeps.txtar000066400000000000000000000002241474664451600243470ustar00rootroot00000000000000-- out/modfetch -- { a: "hello" } -- cue.mod/module.cue -- module: "main.org" language: version: "v0.8.0" -- main.cue -- package main a: "hello" cue-lang-cue-db9cc73/cue/load/testdata/testfetch/simple.txtar000066400000000000000000000044641474664451600243620ustar00rootroot00000000000000-- out/modfetch -- { "foo.com/bar/hello@v0": "v0.2.3" "bar.com@v0": "v0.5.0" "baz.org@v0": "v0.10.1" main: "main" "example.com@v0": "v0.0.1" } -- cue.mod/module.cue -- module: "main.org" language: version: "v0.8.0" deps: { "example.com@v0": v: "v0.0.1" "foo.com/bar/hello@v0": v: "v0.2.3" "baz.org@v0": v: "v0.10.1" } -- main.cue -- package main import "example.com@v0:main" main -- _registry/example.com_v0.0.1/cue.mod/module.cue -- module: "example.com@v0" language: version: "v0.8.0" deps: { "foo.com/bar/hello@v0": v: "v0.2.3" "bar.com@v0": v: "v0.5.0" } -- _registry/example.com_v0.0.1/top.cue -- package main // Note: import without a major version takes // the major version from the module.cue file. import a "foo.com/bar/hello" a main: "main" "example.com@v0": "v0.0.1" -- _registry/foo.com_bar_hello_v0.2.3/cue.mod/module.cue -- module: "foo.com/bar/hello@v0" language: version: "v0.8.0" deps: { "bar.com@v0": v: "v0.0.2" "baz.org@v0": v: "v0.10.1" } -- _registry/foo.com_bar_hello_v0.2.3/x.cue -- package hello import ( a "bar.com/bar@v0" b "baz.org@v0:baz" ) "foo.com/bar/hello@v0": "v0.2.3" a b -- _registry/bar.com_v0.0.2/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.0.2" -- _registry/bar.com_v0.0.2/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.0.2" a -- _registry/bar.com_v0.5.0/cue.mod/module.cue -- module: "bar.com@v0" language: version: "v0.8.0" deps: "baz.org@v0": v: "v0.5.0" -- _registry/bar.com_v0.5.0/bar/x.cue -- package bar import a "baz.org@v0:baz" "bar.com@v0": "v0.5.0" a -- _registry/baz.org_v0.0.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.0.2/baz.cue -- package baz "baz.org@v0": "v0.0.2" -- _registry/baz.org_v0.1.2/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.1.2/baz.cue -- package baz "baz.org@v0": "v0.1.2" -- _registry/baz.org_v0.5.0/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.5.0/baz.cue -- package baz "baz.org@v0": "v0.5.0" -- _registry/baz.org_v0.10.1/cue.mod/module.cue -- module: "baz.org@v0" language: version: "v0.8.0" -- _registry/baz.org_v0.10.1/baz.cue -- package baz "baz.org@v0": "v0.10.1" cue-lang-cue-db9cc73/cue/load/testdata/testmod-external/000077500000000000000000000000001474664451600233035ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod-external/cue.mod/000077500000000000000000000000001474664451600246355ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod-external/cue.mod/module.cue000066400000000000000000000001321474664451600266140ustar00rootroot00000000000000module: "main.example@v0" language: version: "v0.8.0" deps: "foo.example@v0": v: "v0.0.1" cue-lang-cue-db9cc73/cue/load/testdata/testmod-external/main.cue000066400000000000000000000001101474664451600247150ustar00rootroot00000000000000package main import "foo.example/bar@v0" output: "hello, \(bar.value)" cue-lang-cue-db9cc73/cue/load/testdata/testmod/000077500000000000000000000000001474664451600214635ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/anon.cue000066400000000000000000000000161474664451600231110ustar00rootroot00000000000000world: "World"cue-lang-cue-db9cc73/cue/load/testdata/testmod/anon/000077500000000000000000000000001474664451600224165ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/anon/anon.cue000066400000000000000000000000161474664451600240440ustar00rootroot00000000000000world: "World"cue-lang-cue-db9cc73/cue/load/testdata/testmod/anon/dummy000066400000000000000000000000001474664451600234620ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/000077500000000000000000000000001474664451600230155ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/module.cue000066400000000000000000000012101474664451600247720ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. module: "mod.test/test@v0" language: version: "v0.8.0" cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/000077500000000000000000000000001474664451600235765ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/000077500000000000000000000000001474664451600253335ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/catch/000077500000000000000000000000001474664451600264155ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/catch/catch.cue000066400000000000000000000001441474664451600301740ustar00rootroot00000000000000package catch import "mod.test/helper:helper1" Method: "tnt" | "catapult" | "net" | helper.Gotcha cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/cycle/000077500000000000000000000000001474664451600264325ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/cycle/bar/000077500000000000000000000000001474664451600271765ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/cycle/bar/bar.cue000066400000000000000000000001251474664451600304360ustar00rootroot00000000000000package bar import "mod.test/cycle/foo" #Bar1: foo.#Foo1 + 8 #Bar2: foo.#Foo2 + 16 cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/cycle/foo/000077500000000000000000000000001474664451600272155ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/cycle/foo/foo.cue000066400000000000000000000001351474664451600304750ustar00rootroot00000000000000package foo import "mod.test/cycle/bar" #Foo1: 1 #Foo2: bar.#Bar1 + 2 #Foo: bar.#Bar2 + 4 cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/helper/000077500000000000000000000000001474664451600266125ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/helper/helper.cue000066400000000000000000000000411474664451600305620ustar00rootroot00000000000000package helper Gotcha: "gotcha" cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/helper/helper1.cue000066400000000000000000000000421474664451600306440ustar00rootroot00000000000000package helper1 Gotcha: "gotcha" cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/mod.test/helper/helper2.cue000066400000000000000000000000421474664451600306450ustar00rootroot00000000000000package helper2 Gotcha: "gotcha" cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/strconv/000077500000000000000000000000001474664451600252745ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cue.mod/pkg/strconv/strconv.cue000066400000000000000000000002051474664451600274650ustar00rootroot00000000000000// Note: this is an invalidate substitute for the stdlib strconv // package and should not be considered for import. package strconv cue-lang-cue-db9cc73/cue/load/testdata/testmod/cycle/000077500000000000000000000000001474664451600225625ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/cycle/cycle.cue000066400000000000000000000000721474664451600243560ustar00rootroot00000000000000package cycle import "mod.test/cycle/foo" Foo: foo.#Foo cue-lang-cue-db9cc73/cue/load/testdata/testmod/empty/000077500000000000000000000000001474664451600226215ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/empty/dummy000066400000000000000000000000001474664451600236650ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/example/000077500000000000000000000000001474664451600231165ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/example/example.cue000066400000000000000000000000671474664451600252520ustar00rootroot00000000000000package example output: "Hello \(name)" name: "Joe" cue-lang-cue-db9cc73/cue/load/testdata/testmod/hello/000077500000000000000000000000001474664451600225665ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/hello/test.cue000066400000000000000000000000341474664451600242400ustar00rootroot00000000000000package test "Hello world!"cue-lang-cue-db9cc73/cue/load/testdata/testmod/imports/000077500000000000000000000000001474664451600231605ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/imports/imports.cue000066400000000000000000000001571474664451600253560ustar00rootroot00000000000000package imports import "mod.test/catch" coyoteTry1: catch.Method & "tnt" coyoteTry2: catch.Method & =~"cat" cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/000077500000000000000000000000001474664451600231275ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/a/000077500000000000000000000000001474664451600233475ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/a/a.cue000066400000000000000000000000201474664451600242550ustar00rootroot00000000000000package a a: 4 cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/a/b.cue000066400000000000000000000000201474664451600242560ustar00rootroot00000000000000package b b: 3 cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/a/x.cue000066400000000000000000000000121474664451600243050ustar00rootroot00000000000000package x cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/x.cue000066400000000000000000000000201474664451600240640ustar00rootroot00000000000000package x x: 5 cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/x/000077500000000000000000000000001474664451600233765ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/issue3306/x/x.cue000066400000000000000000000000121474664451600243340ustar00rootroot00000000000000package x cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi/000077500000000000000000000000001474664451600226155ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi/file.cue000066400000000000000000000000571474664451600242340ustar00rootroot00000000000000// Test data - not compiled. package main {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi/file_appengine.cue000066400000000000000000000000671474664451600262630ustar00rootroot00000000000000// Test data - not compiled. package test_package {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi/nopackage1.cue000066400000000000000000000000061474664451600253200ustar00rootroot00000000000000x: 1 cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi2/000077500000000000000000000000001474664451600226775ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi2/anon.cue000066400000000000000000000000011474664451600243170ustar00rootroot00000000000000 cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi2/other.cue000066400000000000000000000001471474664451600245200ustar00rootroot00000000000000package other import "mod.test/test/sub" // This is a non-default package for the directory. x: sub cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi3/000077500000000000000000000000001474664451600227005ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi3/multi3.cue000066400000000000000000000001021474664451600246040ustar00rootroot00000000000000package multi3 // This is the default package for the directory. cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi3/other.cue000066400000000000000000000001471474664451600245210ustar00rootroot00000000000000package other import "mod.test/test/sub" // This is a non-default package for the directory. x: sub cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi4/000077500000000000000000000000001474664451600227015ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi4/file.cue000066400000000000000000000000571474664451600243200ustar00rootroot00000000000000// Test data - not compiled. package main {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi4/file_appengine.cue000066400000000000000000000000671474664451600263470ustar00rootroot00000000000000// Test data - not compiled. package test_package {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi4/nopackage1.cue000066400000000000000000000000061474664451600254040ustar00rootroot00000000000000x: 1 cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi4/nopackage2.cue000066400000000000000000000001501474664451600254050ustar00rootroot00000000000000// The underscore package should be treated the same as an omitted package // clause. package _ x: 1 cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/000077500000000000000000000000001474664451600227025ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/file.cue000066400000000000000000000000571474664451600243210ustar00rootroot00000000000000// Test data - not compiled. package main {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/multi/000077500000000000000000000000001474664451600240345ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/multi/file.cue000066400000000000000000000000571474664451600254530ustar00rootroot00000000000000// Test data - not compiled. package main {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/multi/file_appengine.cue000066400000000000000000000000671474664451600275020ustar00rootroot00000000000000// Test data - not compiled. package test_package {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/multi/nopackage1.cue000066400000000000000000000000061474664451600265370ustar00rootroot00000000000000x: 1 cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/multi/nopackage2.cue000066400000000000000000000001501474664451600265400ustar00rootroot00000000000000// The underscore package should be treated the same as an omitted package // clause. package _ x: 1 cue-lang-cue-db9cc73/cue/load/testdata/testmod/multi5/nopackage.cue000066400000000000000000000001501474664451600253240ustar00rootroot00000000000000// The underscore package should be treated the same as an omitted package // clause. package _ x: 1 cue-lang-cue-db9cc73/cue/load/testdata/testmod/other/000077500000000000000000000000001474664451600226045ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/other/anon.cue000066400000000000000000000000461474664451600242350ustar00rootroot00000000000000hello: "Hello \(world)" world: stringcue-lang-cue-db9cc73/cue/load/testdata/testmod/other/file/000077500000000000000000000000001474664451600235235ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/other/file/file.cue000066400000000000000000000000211474664451600251310ustar00rootroot00000000000000package file {} cue-lang-cue-db9cc73/cue/load/testdata/testmod/other/main.cue000066400000000000000000000001041474664451600242210ustar00rootroot00000000000000// Test data - not compiled. package main import ( "./file" ) {}cue-lang-cue-db9cc73/cue/load/testdata/testmod/sub/000077500000000000000000000000001474664451600222545ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/sub/sub.cue000066400000000000000000000011511474664451600235410ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sub User: "sub" cue-lang-cue-db9cc73/cue/load/testdata/testmod/tags/000077500000000000000000000000001474664451600224215ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/tags/prod.cue000066400000000000000000000000571474664451600240650ustar00rootroot00000000000000@if(prod) package tags foo: string @tag(foo) cue-lang-cue-db9cc73/cue/load/testdata/testmod/tags/stage.cue000066400000000000000000000000311474664451600242140ustar00rootroot00000000000000@if(stage) package tags cue-lang-cue-db9cc73/cue/load/testdata/testmod/tagsbad/000077500000000000000000000000001474664451600230705ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/tagsbad/prod.cue000066400000000000000000000000431474664451600245270ustar00rootroot00000000000000@if(foo) @if(bar) package tagsbad cue-lang-cue-db9cc73/cue/load/testdata/testmod/tagsbad/stage.cue000066400000000000000000000000331474664451600246650ustar00rootroot00000000000000package tagsbad @if(prod) cue-lang-cue-db9cc73/cue/load/testdata/testmod/tagswithimports/000077500000000000000000000000001474664451600247335ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/tagswithimports/nonprod.cue000066400000000000000000000001151474664451600271050ustar00rootroot00000000000000@if(!prod) package tagswithimports import "bad-import.example/foo" x: foo cue-lang-cue-db9cc73/cue/load/testdata/testmod/tagswithimports/prod.cue000066400000000000000000000001201474664451600263660ustar00rootroot00000000000000@if(prod) package tagswithimports import "mod.test/test/hello:test" x: hello cue-lang-cue-db9cc73/cue/load/testdata/testmod/test.cue000066400000000000000000000001041474664451600231330ustar00rootroot00000000000000package test import "mod.test/test/sub" out: "Hello \(sub.User)!" cue-lang-cue-db9cc73/cue/load/testdata/testmod/testdir.cue/000077500000000000000000000000001474664451600237145ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/testdir.cue/test.cue000066400000000000000000000000451474664451600253700ustar00rootroot00000000000000package testdir "data from testdir" cue-lang-cue-db9cc73/cue/load/testdata/testmod/toolonly/000077500000000000000000000000001474664451600233425ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod/toolonly/foo_tool.cue000066400000000000000000000001351474664451600256570ustar00rootroot00000000000000package foo import "tool/cli" command: foo: task: { foo: cli.Print & { text: "foo" } } cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacy/000077500000000000000000000000001474664451600230075ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacy/cue.mod/000077500000000000000000000000001474664451600243415ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacy/cue.mod/module.cue000066400000000000000000000002751474664451600263300ustar00rootroot00000000000000// Note: no major version suffix. module: "test.example/foo" // Note: no language.version field present. // Note: extra field not allowed by later strict module versions. extraField: 124 cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacy/foo.cue000066400000000000000000000000151474664451600242640ustar00rootroot00000000000000package foo cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacymodfile/000077500000000000000000000000001474664451600243475ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacymodfile/cue.mod000066400000000000000000000000331474664451600256200ustar00rootroot00000000000000module: "test.example/foo" cue-lang-cue-db9cc73/cue/load/testdata/testmod_legacymodfile/foo.cue000066400000000000000000000000151474664451600256240ustar00rootroot00000000000000package foo cue-lang-cue-db9cc73/cue/marshal.go000066400000000000000000000123231474664451600172330ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "bytes" "compress/gzip" "encoding/gob" "path/filepath" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/format" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/core/export" ) // root. type instanceData struct { Root bool Path string Files []fileData } type fileData struct { Name string Data []byte } const version = 1 type unmarshaller struct { ctxt *build.Context imports map[string]*instanceData } func (b *unmarshaller) load(pos token.Pos, path string) *build.Instance { bi := b.imports[path] if bi == nil { return nil } return b.build(bi) } func (b *unmarshaller) build(bi *instanceData) *build.Instance { p := b.ctxt.NewInstance(bi.Path, b.load) p.ImportPath = bi.Path for _, f := range bi.Files { _ = p.AddFile(f.Name, f.Data) } p.Complete() return p } func compileInstances(r *Runtime, data []*instanceData) (instances []*Instance, err error) { b := unmarshaller{ ctxt: build.NewContext(), imports: map[string]*instanceData{}, } for _, i := range data { if i.Path == "" { if !i.Root { return nil, errors.Newf(token.NoPos, "data contains non-root package without import path") } continue } b.imports[i.Path] = i } builds := []*build.Instance{} for _, i := range data { if !i.Root { continue } builds = append(builds, b.build(i)) } return r.BuildInstances(builds) } // Unmarshal returns a slice of instances from bytes generated by // [Runtime.Marshal]. func (r *Runtime) Unmarshal(b []byte) ([]*Instance, error) { if len(b) == 0 { return nil, errors.Newf(token.NoPos, "unmarshal failed: empty buffer") } switch b[0] { case version: default: return nil, errors.Newf(token.NoPos, "unmarshal failed: unsupported version %d, regenerate data", b[0]) } reader, err := gzip.NewReader(bytes.NewReader(b[1:])) if err != nil { return nil, errors.Newf(token.NoPos, "unmarshal failed: %v", err) } data := []*instanceData{} err = gob.NewDecoder(reader).Decode(&data) if err != nil { return nil, errors.Newf(token.NoPos, "unmarshal failed: %v", err) } return compileInstances(r, data) } // Marshal creates bytes from a group of instances. Imported instances will // be included in the emission. // // The stored instances are functionally the same, but preserving of file // information is only done on a best-effort basis. func (r *Runtime) Marshal(values ...InstanceOrValue) (b []byte, err error) { staged := []instanceData{} done := map[string]int{} var errs errors.Error var stageInstance func(i Value) (pos int) stageInstance = func(i Value) (pos int) { inst := i.BuildInstance() if p, ok := done[inst.ImportPath]; ok { return p } // TODO: support exporting instance file, _ := export.Def(r.runtime(), inst.ID(), i.instance().root) imports := []string{} file.VisitImports(func(i *ast.ImportDecl) { for _, spec := range i.Specs { info, _ := astutil.ParseImportSpec(spec) imports = append(imports, info.ID) } }) if inst.PkgName != "" { if pkg := internal.Package(file); pkg == nil { pkg := &ast.Package{Name: ast.NewIdent(inst.PkgName)} file.Decls = append([]ast.Decl{pkg}, file.Decls...) } else if pkg.Name.Name != inst.PkgName { // pi is guaranteed to be generated by Def, so it is "safe" to modify. pkg.Name = ast.NewIdent(inst.PkgName) } } b, err := format.Node(file) errs = errors.Append(errs, errors.Promote(err, "marshal")) filename := "unmarshal" if len(inst.Files) == 1 { filename = inst.Files[0].Filename dir := inst.Dir if inst.Root != "" { dir = inst.Root } if dir != "" { filename = filepath.FromSlash(filename) filename, _ = filepath.Rel(dir, filename) filename = filepath.ToSlash(filename) } } // TODO: this should probably be changed upstream, but as the path // is for reference purposes only, this is safe. importPath := filepath.ToSlash(i.instance().ImportPath) staged = append(staged, instanceData{ Path: importPath, Files: []fileData{{filename, b}}, }) p := len(staged) - 1 for _, imp := range imports { i := getImportFromPath(r.runtime(), imp) if i == nil || !strings.Contains(imp, ".") { continue // a builtin package. } stageInstance(i.Value()) } return p } for _, val := range values { staged[stageInstance(val.Value())].Root = true } buf := &bytes.Buffer{} buf.WriteByte(version) zw := gzip.NewWriter(buf) if err := gob.NewEncoder(zw).Encode(staged); err != nil { return nil, err } if err := zw.Close(); err != nil { return nil, err } return buf.Bytes(), nil } cue-lang-cue-db9cc73/cue/marshal_test.go000066400000000000000000000075471474664451600203060ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "fmt" "strings" "testing" "github.com/google/go-cmp/cmp" ) func TestMarshalling(t *testing.T) { testCases := []struct { filename string input string pkg string }{{ filename: "foo.cue", pkg: "foo", input: `package foo A: int B: string `, }, { filename: "bar.cue", pkg: "bar", input: `package bar "Hello world!" `, }, { filename: "qux.cue", input: ` "Hello world!" `, }, { filename: "baz.cue", pkg: "baz", input: `package baz import "strings" a: strings.TrimSpace(" Hello world! ") `}} for _, tc := range testCases { t.Run(tc.filename, func(t *testing.T) { r := &Runtime{} inst, err := r.Compile(tc.filename, tc.input) if err != nil { t.Fatal(err) } inst.ImportPath = "test/pkg" want := fmt.Sprint(inst.Value()) val := inst.Value() b, err := r.Marshal(&val) if err != nil { t.Fatal(err) } r2 := &Runtime{} instances, err := r2.Unmarshal(b) if err != nil { t.Fatal(err) } inst = instances[0] if inst.ImportPath != "test/pkg" { t.Error("import path was not restored") } got := fmt.Sprint(inst.Value()) if got != want { t.Errorf("\ngot: %q;\nwant: %q", got, want) } }) } } func TestMarshalMultiPackage(t *testing.T) { files := func(s ...string) (a []fileData) { for i, s := range s { a = append(a, fileData{fmt.Sprintf("file%d.cue", i), []byte(s)}) } return a } insts := func(i ...*instanceData) []*instanceData { return i } pkg1 := &instanceData{ true, "mod.test/foo/pkg1", files(` package pkg1 Object: "World" `), } pkg2 := &instanceData{ true, "mod.test/foo/pkg2", files(` package pkg Number: 12 `), } testCases := []struct { instances []*instanceData emit string }{{ insts(&instanceData{true, "", files(`test: "ok"`)}), `{test: "ok"}`, }, { insts(&instanceData{true, "", files( `package test import math2 "math" "Pi: \(math2.Pi)!"`)}), `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`, }, { insts(pkg1, &instanceData{true, "", files( `package test import "mod.test/foo/pkg1" "Hello \(pkg1.Object)!"`), }), `"Hello World!"`, }, { insts(pkg1, &instanceData{true, "", files( `package test import pkg2 "mod.test/foo/pkg1" "Hello \(pkg1)!" pkg1: pkg2.Object`), }), `"Hello World!"`, }, { insts(pkg2, &instanceData{true, "", files( `package test import "mod.test/foo/pkg2" "Hello \(pkg.Number)!"`), }), `"Hello 12!"`, }} strValue := func(a []*Instance) (ret []string) { for _, i := range a { ret = append(ret, strings.TrimSpace((fmt.Sprint(i.Value())))) } return ret } for _, tc := range testCases { t.Run("", func(t *testing.T) { r := &Runtime{} insts, err := compileInstances(r, tc.instances) if err != nil { t.Fatal(err) } want := strValue(insts) vals := make([]InstanceOrValue, 0) for _, inst := range insts { val := inst.Value() vals = append(vals, &val) } b, err := r.Marshal(vals...) if err != nil { t.Fatal(err) } r2 := &Runtime{} insts, err = r2.Unmarshal(b) if err != nil { t.Fatal(err) } got := strValue(insts) if diff := cmp.Diff(got, want); diff != "" { t.Error(diff) } }) } } cue-lang-cue-db9cc73/cue/op.go000066400000000000000000000033371474664451600162270ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cuelang.org/go/internal/core/adt" ) // Op indicates the operation at the top of an expression tree of the expression // use to evaluate a value. type Op = adt.Op // Values of Op. const ( NoOp Op = adt.NoOp AndOp Op = adt.AndOp OrOp Op = adt.OrOp SelectorOp Op = adt.SelectorOp IndexOp Op = adt.IndexOp SliceOp Op = adt.SliceOp CallOp Op = adt.CallOp BooleanAndOp Op = adt.BoolAndOp BooleanOrOp Op = adt.BoolOrOp EqualOp Op = adt.EqualOp NotOp Op = adt.NotOp NotEqualOp Op = adt.NotEqualOp LessThanOp Op = adt.LessThanOp LessThanEqualOp Op = adt.LessEqualOp GreaterThanOp Op = adt.GreaterThanOp GreaterThanEqualOp Op = adt.GreaterEqualOp RegexMatchOp Op = adt.MatchOp NotRegexMatchOp Op = adt.NotMatchOp AddOp Op = adt.AddOp SubtractOp Op = adt.SubtractOp MultiplyOp Op = adt.MultiplyOp FloatQuotientOp Op = adt.FloatQuotientOp IntQuotientOp Op = adt.IntQuotientOp IntRemainderOp Op = adt.IntRemainderOp IntDivideOp Op = adt.IntDivideOp IntModuloOp Op = adt.IntModuloOp InterpolationOp Op = adt.InterpolationOp ) cue-lang-cue-db9cc73/cue/parser/000077500000000000000000000000001474664451600165505ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/parser/doc.go000066400000000000000000000020511474664451600176420ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package parser implements a parser for CUE source files. Input may be // provided in a variety of forms (see the various Parse* functions); the output // is an abstract syntax tree (AST) representing the CUE source. The parser is // invoked through one of the Parse* functions. // // The parser accepts a larger language than is syntactically permitted by the // CUE spec, for simplicity, and for improved robustness in the presence of // syntax errors. package parser cue-lang-cue-db9cc73/cue/parser/error_test.go000066400000000000000000000120351474664451600212700ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file implements a parser test harness. The files in the testdata // directory are parsed and the errors reported are compared against the // error messages expected in the test files. The test files must end in // .src rather than .go so that they are not disturbed by gofmt runs. // // Expected errors are indicated in the test files by putting a comment // of the form /* ERROR "rx" */ immediately following an offending // The harness will verify that an error matching the regular expression // rx is reported at that source position. // // For instance, the following test file indicates that a "not declared" // error should be reported for the undeclared variable x: // // package p // { // a = x /* ERROR "not declared" */ + 1 // } package parser import ( "regexp" "testing" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/scanner" "cuelang.org/go/cue/token" "cuelang.org/go/internal/source" ) func getPos(f *token.File, offset int) token.Pos { if f != nil { return f.Pos(offset, 0) } return token.NoPos } // ERROR comments must be of the form /* ERROR "rx" */ and rx is // a regular expression that matches the expected error message. // The special form /* ERROR HERE "rx" */ must be used for error // messages that appear immediately after a token, rather than at // a token's position. var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`) // expectedErrors collects the regular expressions of ERROR comments found // in files and returns them as a map of error positions to error messages. func expectedErrors(t *testing.T, file *token.File, src []byte) map[token.Pos]string { errors := make(map[token.Pos]string) var s scanner.Scanner // file was parsed already - do not add it again to the file // set otherwise the position information returned here will // not match the position information collected by the parser // file := token.NewFile(filename, -1, len(src)) s.Init(file, src, nil, scanner.ScanComments) var prev token.Pos // position of last non-comment, non-semicolon token var here token.Pos // position immediately after the token at position prev for { pos, tok, lit := s.Scan() pos = pos.WithRel(0) switch tok { case token.EOF: return errors case token.COMMENT: s := errRx.FindStringSubmatch(lit) if len(s) == 3 { pos := prev if s[1] == "HERE" { pos = here } errors[pos] = string(s[2]) } default: prev = pos var l int // token length if tok.IsLiteral() { l = len(lit) } else { l = len(tok.String()) } here = prev.Add(l) } } } // compareErrors compares the map of expected error messages with the list // of found errors and reports discrepancies. func compareErrors(t *testing.T, file *token.File, expected map[token.Pos]string, found []errors.Error) { t.Helper() for _, error := range found { // error.Pos is a Position, but we want // a Pos so we can do a map lookup ePos := error.Position() eMsg := error.Error() pos := getPos(file, ePos.Offset()).WithRel(0) if msg, found := expected[pos]; found { // we expect a message at pos; check if it matches rx, err := regexp.Compile(msg) if err != nil { t.Errorf("%s: %v", ePos, err) continue } if match := rx.MatchString(eMsg); !match { t.Errorf("%s: %q does not match %q", ePos, eMsg, msg) continue } // we have a match - eliminate this error delete(expected, pos) } else { // To keep in mind when analyzing failed test output: // If the same error position occurs multiple times in errors, // this message will be triggered (because the first error at // the position removes this position from the expected errors). t.Errorf("%s: unexpected error: -%q-", ePos, eMsg) } } // there should be no expected errors left if len(expected) > 0 { t.Errorf("%d errors not reported:", len(expected)) for pos, msg := range expected { t.Errorf("%s: -%q-\n", pos, msg) } } } func checkErrors(t *testing.T, filename string, input interface{}) { t.Helper() src, err := source.ReadAll(filename, input) if err != nil { t.Error(err) return } f, err := ParseFile(filename, src, DeclarationErrors, AllErrors) file := f.Pos().File() found := errors.Errors(err) // we are expecting the following errors // (collect these after parsing a file so that it is found in the file set) if file == nil { t.Fatal("no token.File for ast.File") } expected := expectedErrors(t, file, src) // verify errors returned by the parser compareErrors(t, file, expected, found) } cue-lang-cue-db9cc73/cue/parser/example_test.go000066400000000000000000000020211474664451600215640ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package parser_test import ( "fmt" "cuelang.org/go/cue/parser" ) func ExampleParseFile() { // Parse some CUE source but stop after processing the imports. f, err := parser.ParseFile("example.cue", ` import "math" foo: 1 bar: "baz" `, parser.ImportsOnly) if err != nil { fmt.Println(err) return } // Print the imports from the file's AST. for _, s := range f.Imports { fmt.Println(s.Path.Value) } // Output: // "math" } cue-lang-cue-db9cc73/cue/parser/fuzz_test.go000066400000000000000000000036341474664451600211420ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package parser_test import ( "testing" "cuelang.org/go/cue/parser" ) func FuzzParseFile(f *testing.F) { // Add a wide sample of different kinds of supported syntax. f.Add([]byte(` package p import "foo" import b "bar" import . "baz" `)) f.Add([]byte(` // some comment // group // here `)) f.Add([]byte(`"some string"`)) f.Add([]byte(`[1, 2.3, 4M, 5Gi]`)) f.Add([]byte(`if foo { if bar if baz { x } }`)) f.Add([]byte(`[x for x in [a, b, c]]`)) f.Add([]byte(`foo: "bar": (baz): "\(x)": y`)) f.Add([]byte(`{x: _, y: _|_}`)) f.Add([]byte(`3 & int32`)) f.Add([]byte(`string | *"foo"`)) f.Add([]byte(`let x = y`)) f.Add([]byte(`[1+1, 2-2, 3*3, 4/4]`)) f.Add([]byte(`[1>1, 2>=2, 3==3, 4!=4]`)) f.Add([]byte(`[=~"^a"]: bool`)) f.Add([]byte(`[X=string]: Y={}`)) f.Add([]byte(`[len(x), close(y), and([]), or([])]`)) f.Add([]byte(`[null, bool, float, bytes, int16, uint128]`)) f.Add([]byte(`[ [...string], {x: string, ...}]]`)) f.Add([]byte(`{regular: x, required!: x, optional?: x}`)) f.Add([]byte(`{_hidden: x, #Definition: x, αβ: x}`)) f.Add([]byte(`["\u65e5本\U00008a9e", '\xff\u00FF']`)) f.Add([]byte(`["\(expr)", #"\#(expr) \(notexpr)"#]`)) f.Add([]byte(`{@jsonschema(id="foo"), field: string @go(Field)}`)) f.Fuzz(func(t *testing.T, b []byte) { _, err := parser.ParseFile("fuzz.cue", b) if err != nil { t.Skip() } }) } cue-lang-cue-db9cc73/cue/parser/interface.go000066400000000000000000000164201474664451600210420ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file contains the exported entry points for invoking the package parser import ( "cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast/astutil" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/source" ) // Option specifies a parse option. type Option func(p *parser) var ( // PackageClauseOnly causes parsing to stop after the package clause. PackageClauseOnly Option = packageClauseOnly packageClauseOnly = func(p *parser) { p.mode |= packageClauseOnlyMode } // ImportsOnly causes parsing to stop parsing after the import declarations. ImportsOnly Option = importsOnly importsOnly = func(p *parser) { p.mode |= importsOnlyMode } // ParseComments causes comments to be parsed. ParseComments Option = parseComments parseComments = func(p *parser) { p.mode |= parseCommentsMode } // ParseFuncs causes function declarations to be parsed. // // This is an experimental function and the API is likely to // change or dissapear. ParseFuncs Option = parseFuncs parseFuncs = func(p *parser) { p.mode |= parseFuncsMode } // Trace causes parsing to print a trace of parsed productions. Trace Option = traceOpt traceOpt = func(p *parser) { p.mode |= traceMode } // DeclarationErrors causes parsing to report declaration errors. DeclarationErrors Option = declarationErrors declarationErrors = func(p *parser) { p.mode |= declarationErrorsMode } // AllErrors causes all errors to be reported (not just the first 10 on different lines). AllErrors Option = allErrors allErrors = func(p *parser) { p.mode |= allErrorsMode } // AllowPartial allows the parser to be used on a prefix buffer. AllowPartial Option = allowPartial allowPartial = func(p *parser) { p.mode |= partialMode } ) // FromVersion specifies until which legacy version the parser should provide // backwards compatibility. func FromVersion(version int) Option { if version >= 0 { version++ } // Versions: // <0: major version 0 (counting -1000 + x, where x = 100*m+p in 0.m.p // >=0: x+1 in 1.x.y return func(p *parser) { p.version = version } } // DeprecationError is a sentinel error to indicate that an error is // related to an unsupported old CUE syntax. type DeprecationError struct { Version int } func (e *DeprecationError) Error() string { return "try running `cue fix` (possibly with an earlier version, like v0.2.2) to upgrade" } const ( // Latest specifies the latest version of the parser, effectively setting // the strictest implementation. Latest = latest latest = -1000 + (100 * internal.MinorCurrent) + 0 // FullBackwardCompatibility enables all deprecated features that are // currently still supported by the parser. FullBackwardCompatibility = fullCompatibility fullCompatibility = -1000 ) // FileOffset specifies the File position info to use. // // Deprecated: this has no effect. func FileOffset(pos int) Option { return func(p *parser) {} } // A mode value is a set of flags (or 0). // They control the amount of source code parsed and other optional // parser functionality. type mode uint const ( packageClauseOnlyMode mode = 1 << iota // stop parsing after package clause importsOnlyMode // stop parsing after import declarations parseCommentsMode // parse comments and add them to AST parseFuncsMode // parse function declarations (experimental) partialMode traceMode // print a trace of parsed productions declarationErrorsMode // report declaration errors allErrorsMode // report all errors (not just the first 10 on different lines) ) // ParseFile parses the source code of a single CUE source file and returns // the corresponding File node. The source code may be provided via // the filename of the source file, or via the src parameter. // // If src != nil, ParseFile parses the source from src and the filename is // only used when recording position information. The type of the argument // for the src parameter must be string, []byte, or io.Reader. // If src == nil, ParseFile parses the file specified by filename. // // The mode parameter controls the amount of source text parsed and other // optional parser functionality. Position information is recorded in the // file set fset, which must not be nil. // // If the source couldn't be read, the returned AST is nil and the error // indicates the specific failure. If the source was read but syntax // errors were found, the result is a partial AST (with Bad* nodes // representing the fragments of erroneous source code). Multiple errors // are returned via a ErrorList which is sorted by file position. func ParseFile(filename string, src interface{}, mode ...Option) (f *ast.File, err error) { // get source text, err := source.ReadAll(filename, src) if err != nil { return nil, err } var pp parser defer func() { if pp.panicking { _ = recover() } // set result values if f == nil { // source is not a valid CUE source file - satisfy // ParseFile API and return a valid (but) empty *File f = &ast.File{ // Scope: NewScope(nil), } } err = errors.Sanitize(pp.errors) }() // parse source pp.init(filename, text, mode) f = pp.parseFile() if f == nil { return nil, pp.errors } f.Filename = filename astutil.Resolve(f, pp.errf) return f, pp.errors } // ParseExpr is a convenience function for parsing an expression. // The arguments have the same meaning as for Parse, but the source must // be a valid CUE (type or value) expression. Specifically, fset must not // be nil. func ParseExpr(filename string, src interface{}, mode ...Option) (ast.Expr, error) { // get source text, err := source.ReadAll(filename, src) if err != nil { return nil, err } var p parser defer func() { if p.panicking { _ = recover() } err = errors.Sanitize(p.errors) }() // parse expr p.init(filename, text, mode) // Set up pkg-level scopes to avoid nil-pointer errors. // This is not needed for a correct expression x as the // parser will be ok with a nil topScope, but be cautious // in case of an erroneous x. e := p.parseRHS() // If a comma was inserted, consume it; // report an error if there's more tokens. if p.tok == token.COMMA && p.lit == "\n" { p.next() } if p.mode&partialMode == 0 { p.expect(token.EOF) } if p.errors != nil { return nil, p.errors } astutil.ResolveExpr(e, p.errf) return e, p.errors } // parseExprString is a convenience function for obtaining the AST of an // expression x. The position information recorded in the AST is undefined. The // filename used in error messages is the empty string. func parseExprString(x string) (ast.Expr, error) { return ParseExpr("", []byte(x)) } cue-lang-cue-db9cc73/cue/parser/interface_test.go000066400000000000000000000056261474664451600221070ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package parser import ( "reflect" "testing" "cuelang.org/go/cue/ast" "cuelang.org/go/internal/source" ) func Test_readSource(t *testing.T) { type args struct { filename string src interface{} } tests := []struct { name string args args want []byte wantErr bool }{ // TODO: Add test cases. } for _, tt := range tests { got, err := source.ReadAll(tt.args.filename, tt.args.src) if (err != nil) != tt.wantErr { t.Errorf("%q. readSource() error = %v, wantErr %v", tt.name, err, tt.wantErr) continue } if !reflect.DeepEqual(got, tt.want) { t.Errorf("%q. readSource() = %v, want %v", tt.name, got, tt.want) } } } func TestParseFile(t *testing.T) { type args struct { filename string src interface{} options []Option } tests := []struct { name string args args wantF *ast.File wantErr bool }{ // TODO: Add test cases. } for _, tt := range tests { gotF, err := ParseFile(tt.args.filename, tt.args.src, tt.args.options...) if (err != nil) != tt.wantErr { t.Errorf("%q. ParseFile() error = %v, wantErr %v", tt.name, err, tt.wantErr) continue } if !reflect.DeepEqual(gotF, tt.wantF) { t.Errorf("%q. ParseFile() = %v, want %v", tt.name, gotF, tt.wantF) } } } func TestParseExprFrom(t *testing.T) { type args struct { filename string src interface{} mode Option } tests := []struct { name string args args want ast.Expr wantErr bool }{ // TODO: Add test cases. } for _, tt := range tests { got, err := ParseExpr(tt.args.filename, tt.args.src, tt.args.mode) if (err != nil) != tt.wantErr { t.Errorf("%q. ParseExprFrom() error = %v, wantErr %v", tt.name, err, tt.wantErr) continue } if !reflect.DeepEqual(got, tt.want) { t.Errorf("%q. ParseExprFrom() = %v, want %v", tt.name, got, tt.want) } } } func TestParseExprString(t *testing.T) { type args struct { x string } tests := []struct { name string args args want ast.Expr wantErr bool }{ // TODO: Add test cases. } for _, tt := range tests { got, err := parseExprString(tt.args.x) if (err != nil) != tt.wantErr { t.Errorf("%q. ParseExpr() error = %v, wantErr %v", tt.name, err, tt.wantErr) continue } if !reflect.DeepEqual(got, tt.want) { t.Errorf("%q. ParseExpr() = %v, want %v", tt.name, got, tt.want) } } } cue-lang-cue-db9cc73/cue/parser/parser.go000066400000000000000000001143321474664451600203770ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package parser import ( "fmt" "strings" "unicode" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/scanner" "cuelang.org/go/cue/token" "cuelang.org/go/internal" ) // The parser structure holds the parser's internal state. type parser struct { file *token.File errors errors.Error scanner scanner.Scanner // Tracing/debugging mode mode // parsing mode trace bool // == (mode & Trace != 0) panicking bool // set if we are bailing out due to too many errors. indent int // indentation used for tracing output // Comments leadComment *ast.CommentGroup comments *commentState // Next token pos token.Pos // token position tok token.Token // one token look-ahead lit string // token literal // Error recovery // (used to limit the number of calls to sync... functions // w/o making scanning progress - avoids potential endless // loops across multiple parser functions during error recovery) syncPos token.Pos // last synchronization position syncCnt int // number of calls to sync... functions without progress // Non-syntactic parser control exprLev int // < 0: in control clause, >= 0: in expression imports []*ast.ImportSpec // list of imports version int } func (p *parser) init(filename string, src []byte, mode []Option) { for _, f := range mode { f(p) } p.file = token.NewFile(filename, -1, len(src)) var m scanner.Mode if p.mode&parseCommentsMode != 0 { m = scanner.ScanComments } eh := func(pos token.Pos, msg string, args []interface{}) { p.errors = errors.Append(p.errors, errors.Newf(pos, msg, args...)) } p.scanner.Init(p.file, src, eh, m) p.trace = p.mode&traceMode != 0 // for convenience (p.trace is used frequently) p.comments = &commentState{pos: -1} p.next() } type commentState struct { parent *commentState pos int8 groups []*ast.CommentGroup // lists are not attached to nodes themselves. Enclosed expressions may // miss a comment due to commas and line termination. closeLists ensures // that comments will be passed to someone. isList int lastChild ast.Node lastPos int8 } // openComments reserves the next doc comment for the caller and flushes func (p *parser) openComments() *commentState { child := &commentState{ parent: p.comments, } if c := p.comments; c != nil && c.isList > 0 { if c.lastChild != nil { var groups []*ast.CommentGroup for _, cg := range c.groups { if cg.Position == 0 { groups = append(groups, cg) } } groups = append(groups, ast.Comments(c.lastChild)...) for _, cg := range c.groups { if cg.Position != 0 { cg.Position = c.lastPos groups = append(groups, cg) } } ast.SetComments(c.lastChild, groups) c.groups = nil } else { c.lastChild = nil // attach before next for _, cg := range c.groups { cg.Position = 0 } child.groups = c.groups c.groups = nil } } if p.leadComment != nil { child.groups = append(child.groups, p.leadComment) p.leadComment = nil } p.comments = child return child } // openList is used to treat a list of comments as a single comment // position in a production. func (p *parser) openList() { if p.comments.isList > 0 { p.comments.isList++ return } c := &commentState{ parent: p.comments, isList: 1, } p.comments = c } func (c *commentState) add(g *ast.CommentGroup) { g.Position = c.pos c.groups = append(c.groups, g) } func (p *parser) closeList() { c := p.comments if c.lastChild != nil { for _, cg := range c.groups { cg.Position = c.lastPos ast.AddComment(c.lastChild, cg) } c.groups = nil } switch c.isList--; { case c.isList < 0: if !p.panicking { err := errors.Newf(p.pos, "unmatched close list") p.errors = errors.Append(p.errors, err) p.panicking = true panic(err) } case c.isList == 0: parent := c.parent if len(c.groups) > 0 { parent.groups = append(parent.groups, c.groups...) } parent.pos++ p.comments = parent } } func (c *commentState) closeNode(p *parser, n ast.Node) ast.Node { if p.comments != c { if !p.panicking { err := errors.Newf(p.pos, "unmatched comments") p.errors = errors.Append(p.errors, err) p.panicking = true panic(err) } return n } p.comments = c.parent if c.parent != nil { c.parent.lastChild = n c.parent.lastPos = c.pos c.parent.pos++ } for _, cg := range c.groups { if n != nil { if cg != nil { ast.AddComment(n, cg) } } } c.groups = nil return n } func (c *commentState) closeExpr(p *parser, n ast.Expr) ast.Expr { c.closeNode(p, n) return n } func (c *commentState) closeClause(p *parser, n ast.Clause) ast.Clause { c.closeNode(p, n) return n } // ---------------------------------------------------------------------------- // Parsing support func (p *parser) printTrace(a ...interface{}) { const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " const n = len(dots) pos := p.file.Position(p.pos) fmt.Printf("%5d:%3d: ", pos.Line, pos.Column) i := 2 * p.indent for i > n { fmt.Print(dots) i -= n } // i <= n fmt.Print(dots[0:i]) fmt.Println(a...) } func trace(p *parser, msg string) *parser { p.printTrace(msg, "(") p.indent++ return p } // Usage pattern: defer un(trace(p, "...")) func un(p *parser) { p.indent-- p.printTrace(")") } // Advance to the next func (p *parser) next0() { // Because of one-token look-ahead, print the previous token // when tracing as it provides a more readable output. The // very first token (!p.pos.IsValid()) is not initialized // (it is ILLEGAL), so don't print it . if p.trace && p.pos.IsValid() { s := p.tok.String() switch { case p.tok.IsLiteral(): p.printTrace(s, p.lit) case p.tok.IsOperator(), p.tok.IsKeyword(): p.printTrace("\"" + s + "\"") default: p.printTrace(s) } } p.pos, p.tok, p.lit = p.scanner.Scan() } // Consume a comment and return it and the line on which it ends. func (p *parser) consumeComment() (comment *ast.Comment, endline int) { endline = p.file.Line(p.pos) comment = &ast.Comment{Slash: p.pos, Text: p.lit} p.next0() return } // Consume a group of adjacent comments, add it to the parser's // comments list, and return it together with the line at which // the last comment in the group ends. A non-comment token or n // empty lines terminate a comment group. func (p *parser) consumeCommentGroup(prevLine, n int) (comments *ast.CommentGroup, endline int) { var list []*ast.Comment var rel token.RelPos endline = p.file.Line(p.pos) switch endline - prevLine { case 0: rel = token.Blank case 1: rel = token.Newline default: rel = token.NewSection } for p.tok == token.COMMENT && p.file.Line(p.pos) <= endline+n { var comment *ast.Comment comment, endline = p.consumeComment() list = append(list, comment) } cg := &ast.CommentGroup{List: list} ast.SetRelPos(cg, rel) comments = cg return } // Advance to the next non-comment In the process, collect // any comment groups encountered, and refield the last lead and // line comments. // // A lead comment is a comment group that starts and ends in a // line without any other tokens and that is followed by a non-comment // token on the line immediately after the comment group. // // A line comment is a comment group that follows a non-comment // token on the same line, and that has no tokens after it on the line // where it ends. // // Lead and line comments may be considered documentation that is // stored in the AST. func (p *parser) next() { // A leadComment may not be consumed if it leads an inner token of a node. if p.leadComment != nil { p.comments.add(p.leadComment) } p.leadComment = nil prev := p.pos p.next0() p.comments.pos++ if p.tok == token.COMMENT { var comment *ast.CommentGroup var endline int currentLine := p.file.Line(p.pos) prevLine := p.file.Line(prev) if prevLine == currentLine { // The comment is on same line as the previous token; it // cannot be a lead comment but may be a line comment. comment, endline = p.consumeCommentGroup(prevLine, 0) if p.file.Line(p.pos) != endline { // The next token is on a different line, thus // the last comment group is a line comment. comment.Line = true } } // consume successor comments, if any endline = -1 for p.tok == token.COMMENT { if comment != nil { p.comments.add(comment) } comment, endline = p.consumeCommentGroup(prevLine, 1) prevLine = currentLine currentLine = p.file.Line(p.pos) } if endline+1 == p.file.Line(p.pos) && p.tok != token.EOF { // The next token is following on the line immediately after the // comment group, thus the last comment group is a lead comment. comment.Doc = true p.leadComment = comment } else { p.comments.add(comment) } } } // assertV0 indicates the last version at which a certain feature was // supported. func (p *parser) assertV0(pos token.Pos, minor, patch int, name string) { v := internal.Version(minor, patch) base := p.version if base == 0 { base = internal.APIVersionSupported } if base > v { p.errors = errors.Append(p.errors, errors.Wrapf(&DeprecationError{v}, pos, "use of deprecated %s (deprecated as of v0.%d.%d)", name, minor, patch+1)) } } func (p *parser) errf(pos token.Pos, msg string, args ...interface{}) { // ePos := p.file.Position(pos) ePos := pos // If AllErrors is not set, discard errors reported on the same line // as the last recorded error and stop parsing if there are more than // 10 errors. if p.mode&allErrorsMode == 0 { errors := errors.Errors(p.errors) n := len(errors) if n > 0 && errors[n-1].Position().Line() == ePos.Line() { return // discard - likely a spurious error } if n > 10 { p.panicking = true panic("too many errors") } } p.errors = errors.Append(p.errors, errors.Newf(ePos, msg, args...)) } func (p *parser) errorExpected(pos token.Pos, obj string) { if pos != p.pos { p.errf(pos, "expected %s", obj) return } // the error happened at the current position; // make the error message more specific if p.tok == token.COMMA && p.lit == "\n" { p.errf(pos, "expected %s, found newline", obj) return } if p.tok.IsLiteral() { p.errf(pos, "expected %s, found '%s' %s", obj, p.tok, p.lit) } else { p.errf(pos, "expected %s, found '%s'", obj, p.tok) } } func (p *parser) expect(tok token.Token) token.Pos { pos := p.pos if p.tok != tok { p.errorExpected(pos, "'"+tok.String()+"'") } p.next() // make progress return pos } // expectClosing is like expect but provides a better error message // for the common case of a missing comma before a newline. func (p *parser) expectClosing(tok token.Token, context string) token.Pos { if p.tok != tok && p.tok == token.COMMA && p.lit == "\n" { p.errf(p.pos, "missing ',' before newline in %s", context) p.next() } return p.expect(tok) } func (p *parser) expectComma() { // semicolon is optional before a closing ')', ']', '}', or newline if p.tok != token.RPAREN && p.tok != token.RBRACE && p.tok != token.EOF { switch p.tok { case token.COMMA: p.next() default: p.errorExpected(p.pos, "','") syncExpr(p) } } } func (p *parser) atComma(context string, follow ...token.Token) bool { if p.tok == token.COMMA { return true } for _, t := range follow { if p.tok == t { return false } } // TODO: find a way to detect crossing lines now we don't have a semi. if p.lit == "\n" { p.errf(p.pos, "missing ',' before newline") } else { p.errf(p.pos, "missing ',' in %s", context) } return true // "insert" comma and continue } // syncExpr advances to the next field in a field list. // Used for synchronization after an error. func syncExpr(p *parser) { for { switch p.tok { case token.COMMA: // Return only if parser made some progress since last // sync or if it has not reached 10 sync calls without // progress. Otherwise consume at least one token to // avoid an endless parser loop (it is possible that // both parseOperand and parseStmt call syncStmt and // correctly do not advance, thus the need for the // invocation limit p.syncCnt). if p.pos == p.syncPos && p.syncCnt < 10 { p.syncCnt++ return } if p.syncPos.Before(p.pos) { p.syncPos = p.pos p.syncCnt = 0 return } // Reaching here indicates a parser bug, likely an // incorrect token list in this function, but it only // leads to skipping of possibly correct code if a // previous error is present, and thus is preferred // over a non-terminating parse. case token.EOF: return } p.next() } } // safePos returns a valid file position for a given position: If pos // is valid to begin with, safePos returns pos. If pos is out-of-range, // safePos returns the EOF position. // // This is hack to work around "artificial" end positions in the AST which // are computed by adding 1 to (presumably valid) token positions. If the // token positions are invalid due to parse errors, the resulting end position // may be past the file's EOF position, which would lead to panics if used // later on. func (p *parser) safePos(pos token.Pos) (res token.Pos) { defer func() { if recover() != nil { res = p.file.Pos(p.file.Base()+p.file.Size(), pos.RelPos()) // EOF position } }() _ = p.file.Offset(pos) // trigger a panic if position is out-of-range return pos } // ---------------------------------------------------------------------------- // Identifiers func (p *parser) parseIdent() *ast.Ident { c := p.openComments() pos := p.pos name := "_" if p.tok == token.IDENT { name = p.lit p.next() } else { p.expect(token.IDENT) // use expect() error handling } ident := &ast.Ident{NamePos: pos, Name: name} c.closeNode(p, ident) return ident } func (p *parser) parseKeyIdent() *ast.Ident { c := p.openComments() pos := p.pos name := p.lit p.next() ident := &ast.Ident{NamePos: pos, Name: name} c.closeNode(p, ident) return ident } // ---------------------------------------------------------------------------- // Expressions // parseOperand returns an expression. // Callers must verify the result. func (p *parser) parseOperand() (expr ast.Expr) { if p.trace { defer un(trace(p, "Operand")) } switch p.tok { case token.IDENT: return p.parseIdent() case token.LBRACE: return p.parseStruct() case token.LBRACK: return p.parseList() case token.FUNC: if p.mode&parseFuncsMode != 0 { return p.parseFunc() } else { return p.parseKeyIdent() } case token.BOTTOM: c := p.openComments() x := &ast.BottomLit{Bottom: p.pos} p.next() return c.closeExpr(p, x) case token.NULL, token.TRUE, token.FALSE, token.INT, token.FLOAT, token.STRING: c := p.openComments() x := &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit} p.next() return c.closeExpr(p, x) case token.INTERPOLATION: return p.parseInterpolation() case token.LPAREN: c := p.openComments() defer func() { c.closeNode(p, expr) }() lparen := p.pos p.next() p.exprLev++ p.openList() x := p.parseRHS() // types may be parenthesized: (some type) p.closeList() p.exprLev-- rparen := p.expect(token.RPAREN) return &ast.ParenExpr{ Lparen: lparen, X: x, Rparen: rparen} default: if p.tok.IsKeyword() { return p.parseKeyIdent() } } // we have an error c := p.openComments() pos := p.pos p.errorExpected(pos, "operand") syncExpr(p) return c.closeExpr(p, &ast.BadExpr{From: pos, To: p.pos}) } func (p *parser) parseIndexOrSlice(x ast.Expr) (expr ast.Expr) { if p.trace { defer un(trace(p, "IndexOrSlice")) } c := p.openComments() defer func() { c.closeNode(p, expr) }() c.pos = 1 const N = 2 lbrack := p.expect(token.LBRACK) p.exprLev++ var index [N]ast.Expr var colons [N - 1]token.Pos if p.tok != token.COLON { index[0] = p.parseRHS() } nColons := 0 for p.tok == token.COLON && nColons < len(colons) { colons[nColons] = p.pos nColons++ p.next() if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF { index[nColons] = p.parseRHS() } } p.exprLev-- rbrack := p.expect(token.RBRACK) if nColons > 0 { return &ast.SliceExpr{ X: x, Lbrack: lbrack, Low: index[0], High: index[1], Rbrack: rbrack} } return &ast.IndexExpr{ X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack} } func (p *parser) parseCallOrConversion(fun ast.Expr) (expr *ast.CallExpr) { if p.trace { defer un(trace(p, "CallOrConversion")) } c := p.openComments() defer func() { c.closeNode(p, expr) }() p.openList() defer p.closeList() lparen := p.expect(token.LPAREN) p.exprLev++ var list []ast.Expr for p.tok != token.RPAREN && p.tok != token.EOF { list = append(list, p.parseRHS()) // builtins may expect a type: make(some type, ...) if !p.atComma("argument list", token.RPAREN) { break } p.next() } p.exprLev-- rparen := p.expectClosing(token.RPAREN, "argument list") return &ast.CallExpr{ Fun: fun, Lparen: lparen, Args: list, Rparen: rparen} } // TODO: inline this function in parseFieldList once we no longer user comment // position information in parsing. func (p *parser) consumeDeclComma() { if p.atComma("struct literal", token.RBRACE, token.EOF) { p.next() } } func (p *parser) parseFieldList() (list []ast.Decl) { if p.trace { defer un(trace(p, "FieldList")) } p.openList() defer p.closeList() for p.tok != token.RBRACE && p.tok != token.EOF { switch p.tok { case token.ATTRIBUTE: list = append(list, p.parseAttribute()) p.consumeDeclComma() case token.ELLIPSIS: c := p.openComments() ellipsis := &ast.Ellipsis{Ellipsis: p.pos} p.next() c.closeNode(p, ellipsis) list = append(list, ellipsis) p.consumeDeclComma() default: list = append(list, p.parseField()) } // TODO: handle next comma here, after disallowing non-colon separator // and we have eliminated the need comment positions. } return } func (p *parser) parseLetDecl() (decl ast.Decl, ident *ast.Ident) { if p.trace { defer un(trace(p, "Field")) } c := p.openComments() letPos := p.expect(token.LET) if p.tok != token.IDENT { c.closeNode(p, ident) return nil, &ast.Ident{ NamePos: letPos, Name: "let", } } defer func() { c.closeNode(p, decl) }() ident = p.parseIdent() assign := p.expect(token.BIND) expr := p.parseRHS() p.consumeDeclComma() return &ast.LetClause{ Let: letPos, Ident: ident, Equal: assign, Expr: expr, }, nil } func (p *parser) parseComprehension() (decl ast.Decl, ident *ast.Ident) { if p.trace { defer un(trace(p, "Comprehension")) } c := p.openComments() defer func() { c.closeNode(p, decl) }() tok := p.tok pos := p.pos clauses, fc := p.parseComprehensionClauses(true) if fc != nil { ident = &ast.Ident{ NamePos: pos, Name: tok.String(), } fc.closeNode(p, ident) return nil, ident } sc := p.openComments() expr := p.parseStruct() sc.closeExpr(p, expr) if p.atComma("struct literal", token.RBRACE) { // TODO: may be EOF p.next() } return &ast.Comprehension{ Clauses: clauses, Value: expr, }, nil } func (p *parser) parseField() (decl ast.Decl) { if p.trace { defer un(trace(p, "Field")) } c := p.openComments() defer func() { c.closeNode(p, decl) }() pos := p.pos this := &ast.Field{Label: nil} m := this tok := p.tok label, expr, decl, ok := p.parseLabel(false) if decl != nil { return decl } m.Label = label if !ok { if expr == nil { expr = p.parseRHS() } if a, ok := expr.(*ast.Alias); ok { p.assertV0(a.Pos(), 1, 3, `old-style alias; use "let X = expr" instead`) p.consumeDeclComma() return a } e := &ast.EmbedDecl{Expr: expr} p.consumeDeclComma() return e } switch p.tok { case token.OPTION, token.NOT: m.Optional = p.pos m.Constraint = p.tok p.next() } // TODO: consider disallowing comprehensions with more than one label. // This can be a bit awkward in some cases, but it would naturally // enforce the proper style that a comprehension be defined in the // smallest possible scope. // allowComprehension = false switch p.tok { case token.COLON: case token.COMMA: p.expectComma() // sync parser. fallthrough case token.RBRACE, token.EOF: if a, ok := expr.(*ast.Alias); ok { p.assertV0(a.Pos(), 1, 3, `old-style alias; use "let X = expr" instead`) return a } switch tok { case token.IDENT, token.LBRACK, token.LPAREN, token.STRING, token.INTERPOLATION, token.NULL, token.TRUE, token.FALSE, token.FOR, token.IF, token.LET, token.IN: return &ast.EmbedDecl{Expr: expr} } fallthrough default: p.errorExpected(p.pos, "label or ':'") return &ast.BadDecl{From: pos, To: p.pos} } m.TokenPos = p.pos m.Token = p.tok if p.tok != token.COLON { p.errorExpected(pos, "':'") } p.next() // : for { if l, ok := m.Label.(*ast.ListLit); ok && len(l.Elts) != 1 { p.errf(l.Pos(), "square bracket must have exactly one element") } label, expr, _, ok := p.parseLabel(true) if !ok || (p.tok != token.COLON && p.tok != token.OPTION && p.tok != token.NOT) { if expr == nil { expr = p.parseRHS() } m.Value = expr break } field := &ast.Field{Label: label} m.Value = &ast.StructLit{Elts: []ast.Decl{field}} m = field switch p.tok { case token.OPTION, token.NOT: m.Optional = p.pos m.Constraint = p.tok p.next() } m.TokenPos = p.pos m.Token = p.tok if p.tok != token.COLON { if p.tok.IsLiteral() { p.errf(p.pos, "expected ':'; found %s", p.lit) } else { p.errf(p.pos, "expected ':'; found %s", p.tok) } break } p.next() } if attrs := p.parseAttributes(); attrs != nil { m.Attrs = attrs } p.consumeDeclComma() return this } func (p *parser) parseAttributes() (attrs []*ast.Attribute) { p.openList() for p.tok == token.ATTRIBUTE { attrs = append(attrs, p.parseAttribute()) } p.closeList() return attrs } func (p *parser) parseAttribute() *ast.Attribute { c := p.openComments() a := &ast.Attribute{At: p.pos, Text: p.lit} p.next() c.closeNode(p, a) return a } func (p *parser) parseLabel(rhs bool) (label ast.Label, expr ast.Expr, decl ast.Decl, ok bool) { tok := p.tok switch tok { case token.FOR, token.IF: if rhs { expr = p.parseExpr() break } comp, ident := p.parseComprehension() if comp != nil { return nil, nil, comp, false } expr = ident case token.LET: let, ident := p.parseLetDecl() if let != nil { return nil, nil, let, false } expr = ident case token.IDENT, token.STRING, token.INTERPOLATION, token.LPAREN, token.NULL, token.TRUE, token.FALSE, token.IN, token.FUNC: expr = p.parseExpr() case token.LBRACK: expr = p.parseRHS() switch x := expr.(type) { case *ast.ListLit: // Note: caller must verify this list is suitable as a label. label, ok = x, true } } switch x := expr.(type) { case *ast.BasicLit: switch x.Kind { case token.STRING, token.NULL, token.TRUE, token.FALSE, token.FUNC: // Keywords that represent operands. // Allowing keywords to be used as a labels should not interfere with // generating good errors: any keyword can only appear on the RHS of a // field (after a ':'), whereas labels always appear on the LHS. label, ok = x, true } case *ast.Ident: if strings.HasPrefix(x.Name, "__") && !rhs { p.errf(x.NamePos, "identifiers starting with '__' are reserved") } expr = p.parseAlias(x) if a, ok := expr.(*ast.Alias); ok { if _, ok = a.Expr.(ast.Label); !ok { break } label = a } else { label = x } ok = true case ast.Label: label, ok = x, true } return label, expr, nil, ok } func (p *parser) parseStruct() (expr ast.Expr) { lbrace := p.expect(token.LBRACE) if p.trace { defer un(trace(p, "StructLit")) } elts := p.parseStructBody() rbrace := p.expectClosing(token.RBRACE, "struct literal") return &ast.StructLit{ Lbrace: lbrace, Elts: elts, Rbrace: rbrace, } } func (p *parser) parseStructBody() []ast.Decl { if p.trace { defer un(trace(p, "StructBody")) } p.exprLev++ var elts []ast.Decl // TODO: consider "stealing" non-lead comments. // for _, cg := range p.comments.groups { // if cg != nil { // elts = append(elts, cg) // } // } // p.comments.groups = p.comments.groups[:0] if p.tok != token.RBRACE { elts = p.parseFieldList() } p.exprLev-- return elts } // parseComprehensionClauses parses either new-style (first==true) // or old-style (first==false). // Should we now disallow keywords as identifiers? If not, we need to // return a list of discovered labels as the alternative. func (p *parser) parseComprehensionClauses(first bool) (clauses []ast.Clause, c *commentState) { // TODO: reuse Template spec, which is possible if it doesn't check the // first is an identifier. for { switch p.tok { case token.FOR: c := p.openComments() forPos := p.expect(token.FOR) if first { switch p.tok { case token.COLON, token.BIND, token.OPTION, token.COMMA, token.EOF: return nil, c } } var key, value *ast.Ident var colon token.Pos value = p.parseIdent() if p.tok == token.COMMA { colon = p.expect(token.COMMA) key = value value = p.parseIdent() } c.pos = 4 // params := p.parseParams(nil, ARROW) clauses = append(clauses, c.closeClause(p, &ast.ForClause{ For: forPos, Key: key, Colon: colon, Value: value, In: p.expect(token.IN), Source: p.parseRHS(), })) case token.IF: c := p.openComments() ifPos := p.expect(token.IF) if first { switch p.tok { case token.COLON, token.BIND, token.OPTION, token.COMMA, token.EOF: return nil, c } } clauses = append(clauses, c.closeClause(p, &ast.IfClause{ If: ifPos, Condition: p.parseRHS(), })) case token.LET: c := p.openComments() letPos := p.expect(token.LET) ident := p.parseIdent() assign := p.expect(token.BIND) expr := p.parseRHS() clauses = append(clauses, c.closeClause(p, &ast.LetClause{ Let: letPos, Ident: ident, Equal: assign, Expr: expr, })) default: return clauses, nil } if p.tok == token.COMMA { p.next() } first = false } } func (p *parser) parseFunc() (expr ast.Expr) { if p.trace { defer un(trace(p, "Func")) } tok := p.tok pos := p.pos fun := p.expect(token.FUNC) // "func" might be used as an identifier, in which case bail out early. switch p.tok { case token.COLON, token.BIND, token.OPTION, token.COMMA, token.EOF: return &ast.Ident{ NamePos: pos, Name: tok.String(), } } p.expect(token.LPAREN) args := p.parseFuncArgs() p.expectClosing(token.RPAREN, "argument type list") p.expect(token.COLON) ret := p.parseExpr() return &ast.Func{ Func: fun, Args: args, Ret: ret, } } func (p *parser) parseFuncArgs() (list []ast.Expr) { if p.trace { defer un(trace(p, "FuncArgs")) } p.openList() defer p.closeList() for p.tok != token.RPAREN && p.tok != token.EOF { list = append(list, p.parseFuncArg()) if p.tok != token.RPAREN { p.expectComma() } } return list } func (p *parser) parseFuncArg() (expr ast.Expr) { if p.trace { defer un(trace(p, "FuncArg")) } return p.parseExpr() } func (p *parser) parseList() (expr ast.Expr) { lbrack := p.expect(token.LBRACK) if p.trace { defer un(trace(p, "ListLiteral")) } elts := p.parseListElements() if p.tok == token.ELLIPSIS { ellipsis := &ast.Ellipsis{ Ellipsis: p.pos, } elts = append(elts, ellipsis) p.next() if p.tok != token.COMMA && p.tok != token.RBRACK { ellipsis.Type = p.parseRHS() } if p.atComma("list literal", token.RBRACK) { p.next() } } rbrack := p.expectClosing(token.RBRACK, "list literal") return &ast.ListLit{ Lbrack: lbrack, Elts: elts, Rbrack: rbrack} } func (p *parser) parseListElements() (list []ast.Expr) { if p.trace { defer un(trace(p, "ListElements")) } p.openList() defer p.closeList() for p.tok != token.RBRACK && p.tok != token.ELLIPSIS && p.tok != token.EOF { expr, ok := p.parseListElement() list = append(list, expr) if !ok { break } } return } func (p *parser) parseListElement() (expr ast.Expr, ok bool) { if p.trace { defer un(trace(p, "ListElement")) } c := p.openComments() defer func() { c.closeNode(p, expr) }() switch p.tok { case token.FOR, token.IF: tok := p.tok pos := p.pos clauses, fc := p.parseComprehensionClauses(true) if clauses != nil { sc := p.openComments() expr := p.parseStruct() sc.closeExpr(p, expr) if p.atComma("list literal", token.RBRACK) { // TODO: may be EOF p.next() } return &ast.Comprehension{ Clauses: clauses, Value: expr, }, true } expr = &ast.Ident{ NamePos: pos, Name: tok.String(), } fc.closeNode(p, expr) default: expr = p.parseUnaryExpr() } expr = p.parseBinaryExprTail(token.LowestPrec+1, expr) expr = p.parseAlias(expr) // Enforce there is an explicit comma. We could also allow the // omission of commas in lists, but this gives rise to some ambiguities // with list comprehensions. if p.tok == token.COMMA && p.lit != "," { p.next() // Allow missing comma for last element, though, to be compliant // with JSON. if p.tok == token.RBRACK || p.tok == token.FOR || p.tok == token.IF { return expr, false } p.errf(p.pos, "missing ',' before newline in list literal") } else if !p.atComma("list literal", token.RBRACK, token.FOR, token.IF) { return expr, false } p.next() return expr, true } // parseAlias turns an expression into an alias. func (p *parser) parseAlias(lhs ast.Expr) (expr ast.Expr) { if p.tok != token.BIND { return lhs } pos := p.pos p.next() expr = p.parseRHS() if expr == nil { panic("empty return") } switch x := lhs.(type) { case *ast.Ident: return &ast.Alias{Ident: x, Equal: pos, Expr: expr} } p.errf(p.pos, "expected identifier for alias") return expr } // checkExpr checks that x is an expression (and not a type). func (p *parser) checkExpr(x ast.Expr) ast.Expr { switch unparen(x).(type) { case *ast.BadExpr: case *ast.BottomLit: case *ast.Ident: case *ast.BasicLit: case *ast.Interpolation: case *ast.Func: case *ast.StructLit: case *ast.ListLit: case *ast.ParenExpr: panic("unreachable") case *ast.SelectorExpr: case *ast.IndexExpr: case *ast.SliceExpr: case *ast.CallExpr: case *ast.UnaryExpr: case *ast.BinaryExpr: default: // all other nodes are not proper expressions p.errorExpected(x.Pos(), "expression") x = &ast.BadExpr{ From: x.Pos(), To: p.safePos(x.End()), } } return x } // If x is of the form (T), unparen returns unparen(T), otherwise it returns x. func unparen(x ast.Expr) ast.Expr { if p, isParen := x.(*ast.ParenExpr); isParen { x = unparen(p.X) } return x } // If lhs is set and the result is an identifier, it is not resolved. func (p *parser) parsePrimaryExpr() ast.Expr { if p.trace { defer un(trace(p, "PrimaryExpr")) } return p.parsePrimaryExprTail(p.parseOperand()) } func (p *parser) parsePrimaryExprTail(operand ast.Expr) ast.Expr { x := operand L: for { switch p.tok { case token.PERIOD: c := p.openComments() c.pos = 1 p.next() switch p.tok { case token.IDENT: x = &ast.SelectorExpr{ X: p.checkExpr(x), Sel: p.parseIdent(), } case token.STRING: if strings.HasPrefix(p.lit, `"`) && !strings.HasPrefix(p.lit, `""`) { str := &ast.BasicLit{ ValuePos: p.pos, Kind: token.STRING, Value: p.lit, } p.next() x = &ast.SelectorExpr{ X: p.checkExpr(x), Sel: str, } break } fallthrough default: if p.tok.IsKeyword() { x = &ast.SelectorExpr{ X: p.checkExpr(x), Sel: p.parseKeyIdent(), } break } pos := p.pos p.errorExpected(pos, "selector") p.next() // make progress x = &ast.SelectorExpr{X: x, Sel: &ast.Ident{NamePos: pos, Name: "_"}} } c.closeNode(p, x) case token.LBRACK: x = p.parseIndexOrSlice(p.checkExpr(x)) case token.LPAREN: x = p.parseCallOrConversion(p.checkExpr(x)) default: break L } } return x } // If lhs is set and the result is an identifier, it is not resolved. func (p *parser) parseUnaryExpr() ast.Expr { if p.trace { defer un(trace(p, "UnaryExpr")) } switch p.tok { case token.ADD, token.SUB, token.NOT, token.MUL, token.LSS, token.LEQ, token.GEQ, token.GTR, token.NEQ, token.MAT, token.NMAT: pos, op := p.pos, p.tok c := p.openComments() p.next() return c.closeExpr(p, &ast.UnaryExpr{ OpPos: pos, Op: op, X: p.checkExpr(p.parseUnaryExpr()), }) } return p.parsePrimaryExpr() } func (p *parser) tokPrec() (token.Token, int) { tok := p.tok if tok == token.IDENT { switch p.lit { case "quo": return token.IQUO, 7 case "rem": return token.IREM, 7 case "div": return token.IDIV, 7 case "mod": return token.IMOD, 7 default: return tok, 0 } } return tok, tok.Precedence() } // If lhs is set and the result is an identifier, it is not resolved. func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { if p.trace { defer un(trace(p, "BinaryExpr")) } p.openList() defer p.closeList() return p.parseBinaryExprTail(prec1, p.parseUnaryExpr()) } func (p *parser) parseBinaryExprTail(prec1 int, x ast.Expr) ast.Expr { for { op, prec := p.tokPrec() if prec < prec1 { return x } c := p.openComments() c.pos = 1 pos := p.expect(p.tok) x = c.closeExpr(p, &ast.BinaryExpr{ X: p.checkExpr(x), OpPos: pos, Op: op, // Treat nested expressions as RHS. Y: p.checkExpr(p.parseBinaryExpr(prec + 1))}) } } func (p *parser) parseInterpolation() (expr ast.Expr) { c := p.openComments() defer func() { c.closeNode(p, expr) }() p.openList() defer p.closeList() cc := p.openComments() lit := p.lit pos := p.pos p.next() last := &ast.BasicLit{ValuePos: pos, Kind: token.STRING, Value: lit} exprs := []ast.Expr{last} for p.tok == token.LPAREN { c.pos = 1 p.expect(token.LPAREN) cc.closeExpr(p, last) exprs = append(exprs, p.parseRHS()) cc = p.openComments() if p.tok != token.RPAREN { p.errf(p.pos, "expected ')' for string interpolation") } lit = p.scanner.ResumeInterpolation() pos = p.pos p.next() last = &ast.BasicLit{ ValuePos: pos, Kind: token.STRING, Value: lit, } exprs = append(exprs, last) } cc.closeExpr(p, last) return &ast.Interpolation{Elts: exprs} } // Callers must check the result (using checkExpr), depending on context. func (p *parser) parseExpr() (expr ast.Expr) { if p.trace { defer un(trace(p, "Expression")) } c := p.openComments() defer func() { c.closeExpr(p, expr) }() return p.parseBinaryExpr(token.LowestPrec + 1) } func (p *parser) parseRHS() ast.Expr { x := p.checkExpr(p.parseExpr()) return x } // ---------------------------------------------------------------------------- // Declarations func isValidImport(lit string) bool { const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" s, _ := literal.Unquote(lit) // go/scanner returns a legal string literal if p := strings.LastIndexByte(s, ':'); p >= 0 { s = s[:p] } for _, r := range s { if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) { return false } } return s != "" } func (p *parser) parseImportSpec(_ int) *ast.ImportSpec { if p.trace { defer un(trace(p, "ImportSpec")) } c := p.openComments() var ident *ast.Ident if p.tok == token.IDENT { ident = p.parseIdent() } pos := p.pos var path string if p.tok == token.STRING { path = p.lit if !isValidImport(path) { p.errf(pos, "invalid import path: %s", path) } p.next() p.expectComma() // call before accessing p.linecomment } else { p.expect(token.STRING) // use expect() error handling if p.tok == token.COMMA { p.expectComma() // call before accessing p.linecomment } } // collect imports spec := &ast.ImportSpec{ Name: ident, Path: &ast.BasicLit{ValuePos: pos, Kind: token.STRING, Value: path}, } c.closeNode(p, spec) p.imports = append(p.imports, spec) return spec } func (p *parser) parseImports() *ast.ImportDecl { if p.trace { defer un(trace(p, "Imports")) } c := p.openComments() ident := p.parseIdent() var lparen, rparen token.Pos var list []*ast.ImportSpec if p.tok == token.LPAREN { lparen = p.pos p.next() p.openList() for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ { list = append(list, p.parseImportSpec(iota)) } p.closeList() rparen = p.expect(token.RPAREN) p.expectComma() } else { list = append(list, p.parseImportSpec(0)) } d := &ast.ImportDecl{ Import: ident.Pos(), Lparen: lparen, Specs: list, Rparen: rparen, } c.closeNode(p, d) return d } // ---------------------------------------------------------------------------- // Source files func (p *parser) parseFile() *ast.File { if p.trace { defer un(trace(p, "File")) } c := p.comments // Don't bother parsing the rest if we had errors scanning the first // Likely not a CUE source file at all. if p.errors != nil { return nil } p.openList() var decls []ast.Decl for p.tok == token.ATTRIBUTE { decls = append(decls, p.parseAttribute()) p.consumeDeclComma() } // The package clause is not a declaration: it does not appear in any // scope. if p.tok == token.IDENT && p.lit == "package" { c := p.openComments() pos := p.pos var name *ast.Ident p.expect(token.IDENT) name = p.parseIdent() if name.Name == "_" && p.mode&declarationErrorsMode != 0 { p.errf(p.pos, "invalid package name _") } pkg := &ast.Package{ PackagePos: pos, Name: name, } decls = append(decls, pkg) p.expectComma() c.closeNode(p, pkg) } for p.tok == token.ATTRIBUTE { decls = append(decls, p.parseAttribute()) p.consumeDeclComma() } if p.mode&packageClauseOnlyMode == 0 { // import decls for p.tok == token.IDENT && p.lit == "import" { decls = append(decls, p.parseImports()) } if p.mode&importsOnlyMode == 0 { // rest of package decls // TODO: loop and allow multiple expressions. decls = append(decls, p.parseFieldList()...) p.expect(token.EOF) } } p.closeList() f := &ast.File{ Imports: p.imports, Decls: decls, } c.closeNode(p, f) return f } cue-lang-cue-db9cc73/cue/parser/parser_test.go000066400000000000000000000437431474664451600214450ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package parser import ( "fmt" "strings" "testing" "cuelang.org/go/cue/ast" "cuelang.org/go/internal/astinternal" ) func TestParse(t *testing.T) { testCases := []struct{ desc, in, out string }{{ "ellipsis in structs", `#Def: { b: "2" ... } ... #Def2: { ... b: "2" } #Def3: {... _} ... `, `#Def: {b: "2", ...}, ..., #Def2: {..., b: "2"}, #Def3: {..., _}, ...`, }, { "empty file", "", "", }, { "empty struct", "{}", "{}", }, { "empty structs", "{},{},", "{}, {}", }, { "empty structs; elided comma", "{}\n{}", "{}, {}", }, { "basic lits", `"a","b", 3,3.4,5,2_3`, `"a", "b", 3, 3.4, 5, 2_3`, }, { "keyword basic lits", `true,false,null,for,in,if,let,if`, `true, false, null, for, in, if, let, if`, }, { "keyword basic newline", ` true false null for in if let if `, `true, false, null, for, in, if, let, if`, }, { "keywords as labels", `if: 0, for: 1, in: 2, where: 3, div: 4, quo: 5, func: 6 for: if: func: let: 3 `, `if: 0, for: 1, in: 2, where: 3, div: 4, quo: 5, func: 6, for: {if: {func: {let: 3}}}`, }, { "keywords as alias", `if=foo: 0 for=bar: 2 let=bar: 3 func=baz: 4 `, `if=foo: 0, for=bar: 2, let=bar: 3, func=baz: 4`, }, { "keywords as selector", `a : { if: 0 for: 1 in: 2 where: 3 div: 4 quo: 5 func: 6 float: 7 null: if: func: let: 3 }, b: [ a.if, a.for, a.in, a.where, a.div, a.quo, a.func, a.float, a.null.if.func.let, ]`, `a: {if: 0, for: 1, in: 2, where: 3, div: 4, quo: 5, func: 6, float: 7, null: {if: {func: {let: 3}}}}, b: [a.if, a.for, a.in, a.where, a.div, a.quo, a.func, a.float, a.null.if.func.let]`, }, {}, { "json", `{ "a": 1, "b": "2", "c": 3 }`, `{"a": 1, "b": "2", "c": 3}`, }, { "json:extra comma", `{ "a": 1, "b": "2", "c": 3, }`, `{"a": 1, "b": "2", "c": 3}`, }, { "json:simplified", `{ a: 1 b: "2" c: 3 }`, `{a: 1, b: "2", c: 3}`, }, { "attributes", `a: 1 @xml(,attr) b: 2 @foo(a,b=4) @go(Foo) c: { d: "x" @go(D) @json(,omitempty) e: "y" @ts(,type=string,"str") }`, `a: 1 @xml(,attr), b: 2 @foo(a,b=4) @go(Foo), c: {d: "x" @go(D) @json(,omitempty), e: "y" @ts(,type=string,"str")}`, }, { "not emitted", `a: true b?: "2" c?: 3 d!: 2 e: f!: 3 "g\("en")"?: 4 "h\("en")"!: 4 `, `a: true, b?: "2", c?: 3, d!: 2, e: {f!: 3}, "g\("en")"?: 4, "h\("en")"!: 4`, }, { "definition", `#Def: { b: "2" c: 3 embedding } #Def: {} `, `#Def: {b: "2", c: 3, embedding}, #Def: {}`, }, { "one-line embedding", `{ V1, V2 }`, `{V1, V2}`, }, { "selectors", `a.b. "str"`, `a.b."str"`, }, { "selectors", `a.b. "str"`, `a.b."str"`, }, { "faulty bytes selector", `a.b.'str'`, "a.b._\nexpected selector, found 'STRING' 'str'", }, { "faulty multiline string selector", `a.b.""" """`, "a.b._\nexpected selector, found 'STRING' \"\"\"\n\t\t\t\"\"\"", }, { "expression embedding", `#Def: { a.b.c a > b < c -1<2 foo: 2 }`, `#Def: {a.b.c, a>b=1 & <=2 b: >2.0 & <= 40.0 c: >"a" & <="b" v: (>=1 & <=2) & <=(>=5 & <=10) w: >1 & <=2 & <=3 d: >=3T & <=5M `, "a: >=1&<=2, b: >2.0&<=40.0, c: >\"a\"&<=\"b\", v: (>=1&<=2)&<=(>=5&<=10), w: >1&<=2&<=3, d: >=3T&<=5M", }, { "indices", `{ a: b[2] b: c[1:2] c: "asdf" d: c ["a"] }`, `{a: b[2], b: c[1:2], c: "asdf", d: c["a"]}`, }, { "calls", `{ a: b(a.b, c.d) b: a.b(c) }`, `{a: b(a.b, c.d), b: a.b(c)}`, }, { "lists", `{ a: [ 1, 2, 3, b, c, ... ] b: [ 1, 2, 3, ], c: [ 1, 2, 3 ], d: [ 1+2, 2, 4,] }`, `{a: [1, 2, 3, b, c, ...], b: [1, 2, 3], c: [1, 2, 3], d: [1+2, 2, 4]}`, }, { "list types", `{ a: 4*[int] b: <=5*[{a: 5}] c1: [...int] c2: [...] c3: [1, 2, ...int,] }`, `{a: 4*[int], b: <=5*[{a: 5}], c1: [...int], c2: [...], c3: [1, 2, ...int]}`, }, { "list comprehensions", `{ y: [1,2,3] b: [for x in y if x == 1 { x }], }`, `{y: [1, 2, 3], b: [for x in y if x==1 {x}]}`, }, { "field comprehensions", `{ y: { a: 1, b: 2} a: { for k, v in y if v > 2 { "\(k)": v } } }`, `{y: {a: 1, b: 2}, a: {for k: v in y if v>2 {"\(k)": v}}}`, }, { "nested comprehensions", `{ y: { a: 1, b: 2} a: { for k, v in y let x = v+2 if x > 2 { "\(k)": v } } }`, `{y: {a: 1, b: 2}, a: {for k: v in y let x=v+2 if x>2 {"\(k)": v}}}`, }, { "let declaration", `{ let X = 42 let Y = "42", let Z = 10 + 12 }`, `{let X=42, let Y="42", let Z=10+12}`, }, { "duplicates allowed", `{ a: b: 3 a: { b: 3 } }`, "{a: {b: 3}, a: {b: 3}}", }, { "templates", // TODO: remove `{ [foo=_]: { a: int } a: { a: 1 } }`, "{[foo=_]: {a: int}, a: {a: 1}}", }, { "value alias", ` { a: X=foo b: Y={foo} c: d: e: X=5 } `, `{a: X=foo, b: Y={foo}, c: {d: {e: X=5}}}`, }, { "dynamic labels", `{ (x): a: int x: "foo" a: { (a.b) } (x)?: 1 y: (x)!: 2 }`, `{(x): {a: int}, x: "foo", a: {(a.b)}, (x)?: 1, y: {(x)!: 2}}`, }, { "foo", `[ [1], [1, 2], [1, 2, 3], ]`, "[[1], [1, 2], [1, 2, 3]]", }, { "interpolation", `a: "foo \(ident)" b: "bar \(bar) $$$ " c: "nest \( { a: "\( nest ) "}.a ) \(5)" m1: """ multi \(bar) """ m2: ''' \(bar) multi '''`, `a: "foo \(ident)", b: "bar \(bar) $$$ ", c: "nest \({a: "\(nest) "}.a) \(5)", ` + "m1: \"\"\"\n\t\t\t multi \\(bar)\n\t\t\t \"\"\", m2: '''\n\t\t\t \\(bar) multi\n\t\t\t '''", }, { "file comments", `// foo // uni package foo // uniline // file.1 // file.2 `, "<[0// foo] <[d0// uni] [l3// uniline] [3// file.1 // file.2] package foo>>", }, { "line comments", `// doc a: 5 // line b: 6 // lineb // next `, // next is followed by EOF. Ensure it doesn't move to file. "<[d0// doc] [l5// line] a: 5>, " + "<[l5// lineb] [5// next] b: 6>", }, { "alt comments", `// a ... a: 5 // line a // about a // b ... b: // lineb 6 // about b c: 7 // about c // about d d: // about e e: 3 `, "<[d0// a ...] [l5// line a] [5// about a] a: 5>, " + "<[d0// b ...] [l2// lineb] [5// about b] b: 6>, " + "<[5// about c] c: 7>, " + "<[d0// about d] d: {<[d0// about e] e>: 3}>", }, { "expr comments", ` a: 2 + // 2 + 3 + // 3 + 4 // 4 `, "<[l5// 4] a: <[l2// 3 +] <[l2// 2 +] 2+3>+4>>", }, { "composit comments", `a : { a: 1, b: 2, c: 3, d: 4 // end } b: [ 1, 2, 3, 4, 5, // end ] c: [ 1, 2, 3, 4, // here { a: 3 }, // here 5, 6, 7, 8 // and here ] d: { a: 1 // Hello // Doc b: 2 } e1: [ // comment in list body ] e2: { // comment in struct body } `, "a: {a: 1, b: 2, c: 3, <[d5// end] d: 4>}, " + "b: [1, 2, 3, 4, <[d2// end] 5>], " + "c: [1, 2, 3, <[l2// here] 4>, <[l4// here] {a: 3}>, 5, 6, 7, <[l2// and here] 8>], " + "d: {<[l5// Hello] a: 1>, <[d0// Doc] b: 2>}, " + "e1: <[d1// comment in list body] []>, " + "e2: <[d1// comment in struct body] {}>", }, { "attribute comments", ` a: 1 @a() @b() // d `, `<[l5// d] a: 1 @a() @b()>`, }, { "attribute declarations", ` @foo() package bar @bar() import "strings" @baz() `, `@foo(), package bar, @bar(), import "strings", @baz()`, }, { "comprehension comments", ` if X { // Comment 1 Field: 2 // Comment 2 } `, `if X <[d2// Comment 2] {<[d0// Comment 1] Field: 2>}>`, }, { "let comments", `let X = foo // Comment 1`, `<[5// Comment 1] let X=foo>`, }, { "emit comments", `// a comment at the beginning of the file // a second comment // comment a: 5 {} // a comment at the end of the file `, "<[0// a comment at the beginning of the file] [0// a second comment] <[d0// comment] a: 5>, <[2// a comment at the end of the file] {}>>", }, { "composite comments 2", ` { // foo // fooo foo: 1 bar: 2 } [ {"name": "value"}, // each element has a long {"name": "next"} // optional next element ] `, `{<[0// foo] [d0// fooo] foo: 1>, bar: 2}, [<[l4// each element has a long] {"name": "value"}>, <[l4// optional next element] {"name": "next"}>]`, }, { desc: "field aliasing", in: ` I="\(k)": v S="foo-bar": w L=foo: x X=[0]: { foo: X | null } [Y=string]: { name: Y } X1=[X2=<"d"]: { name: X2 } Y1=foo: Y2=bar: [Y1, Y2] `, out: `I="\(k)": v, ` + `S="foo-bar": w, ` + `L=foo: x, ` + `X=[0]: {foo: X|null}, ` + `[Y=string]: {name: Y}, ` + `X1=[X2=<"d"]: {name: X2}, ` + `Y1=foo: {Y2=bar: [Y1, Y2]}`, }, { desc: "allow keyword in expression", in: ` foo: in & 2 `, out: "foo: in&2", }, { desc: "dot import", in: ` import . "foo" `, out: "import , \"foo\"\nexpected 'STRING', found '.'", }, { desc: "attributes", in: ` package name @t1(v1) { @t2(v2) } a: { a: 1 @t3(v3) @t4(v4) c: 2 } `, out: "package name, @t1(v1), {@t2(v2)}, a: {a: 1, @t3(v3), @t4(v4), c: 2}", }, { desc: "Issue #276", in: ` a: int=>2 `, out: "a: int=>2", }, { desc: "struct comments", in: ` struct: { // This is a comment // This is a comment // Another comment something: { } // extra comment }`, out: `struct: {<[0// This is a comment] [0// This is a comment] [d0// Another comment] [d5// extra comment] something: {}>}`, }, { desc: "list comments", in: ` list: [ // Comment1 // Comment2 // Another comment { }, // Comment 3 ]`, out: "list: [<[0// Comment1] [0// Comment2] [d0// Another comment] [d3// Comment 3] {}>]", }, { desc: "call comments", in: ` funcArg1: foo( {}, // Comment1 // Comment2 {} // Comment3 )`, out: "funcArg1: foo(<[1// Comment1] {}>, <[d0// Comment2] [d1// Comment3] {}>)", }, { desc: "front-style commas", in: ` frontStyle: { "key": "value" , "key2": "value2" , "foo" : bar } `, out: "frontStyle: {\"key\": \"value\", \"key2\": \"value2\", \"foo\": bar}", }, { desc: "function types", in: ` f0: func(): int f1: func(int): int f2: func(int, string): int f3: func({a: int, b: string}): bool f4: func(bool, func(int, string): int): string f5: func(int, int): func(bool, bool): bool f6: func(func(bool, bool): bool, func(string, string): string): func(int, func(int, string): int): func(int, string): int `, out: "f0: func(): int, f1: func(int): int, f2: func(int, string): int, f3: func({a: int, b: string}): bool, f4: func(bool, func(int, string): int): string, f5: func(int, int): func(bool, bool): bool, f6: func(func(bool, bool): bool, func(string, string): string): func(int, func(int, string): int): func(int, string): int", }} for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { mode := []Option{AllErrors} if strings.Contains(tc.desc, "comments") { mode = append(mode, ParseComments) } if strings.Contains(tc.desc, "function") { mode = append(mode, ParseFuncs) } f, err := ParseFile("input", tc.in, mode...) got := astinternal.DebugStr(f) if err != nil { got += "\n" + err.Error() } if got != tc.out { t.Errorf("\ngot %q;\nwant %q", got, tc.out) } }) } } func TestStrict(t *testing.T) { testCases := []struct{ desc, in string }{ {"block comments", `a: 1 /* a */`}, {"space separator", `a b c: 2`}, {"reserved identifiers", `__foo: 3`}, {"old-style alias 1", `X=3`}, {"old-style alias 2", `X={}`}, // Not yet supported {"additional typed not yet supported", `{...int}`}, } for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { mode := []Option{AllErrors, ParseComments, FromVersion(Latest)} _, err := ParseFile("input", tc.in, mode...) if err == nil { t.Errorf("unexpected success: %v", tc.in) } }) } } func TestParseExpr(t *testing.T) { // just kicking the tires: // a valid arithmetic expression src := "a + b" x, err := parseExprString(src) if err != nil { t.Errorf("ParseExpr(%q): %v", src, err) } // sanity check if _, ok := x.(*ast.BinaryExpr); !ok { t.Errorf("ParseExpr(%q): got %T, want *BinaryExpr", src, x) } // an invalid expression src = "a + *" if _, err := parseExprString(src); err == nil { t.Errorf("ParseExpr(%q): got no error", src) } // a comma is not permitted unless automatically inserted src = "a + b\n" if _, err := parseExprString(src); err != nil { t.Errorf("ParseExpr(%q): got error %s", src, err) } src = "a + b;" if _, err := parseExprString(src); err == nil { t.Errorf("ParseExpr(%q): got no error", src) } // check resolution src = "{ foo: bar, bar: foo }" x, err = parseExprString(src) if err != nil { t.Fatalf("ParseExpr(%q): %v", src, err) } for _, d := range x.(*ast.StructLit).Elts { v := d.(*ast.Field).Value.(*ast.Ident) if v.Scope == nil { t.Errorf("ParseExpr(%q): scope of field %v not set", src, v.Name) } if v.Node == nil { t.Errorf("ParseExpr(%q): scope of node %v not set", src, v.Name) } } // various other stuff following a valid expression const validExpr = "a + b" const anything = "dh3*#D)#_" for _, c := range "!)]};," { src := validExpr + string(c) + anything if _, err := parseExprString(src); err == nil { t.Errorf("ParseExpr(%q): got no error", src) } } // ParseExpr must not crash for _, src := range valids { _, _ = parseExprString(src) } } func TestImports(t *testing.T) { var imports = map[string]bool{ `"a"`: true, `"a/b"`: true, `"a.b"`: true, `'m\x61th'`: true, `"greek/αβ"`: true, `""`: false, // Each of these pairs tests both #""# vs "" strings // and also use of invalid characters spelled out as // escape sequences and written directly. // For example `"\x00"` tests import "\x00" // while "`\x00`" tests import ``. `#"a"#`: true, `"\x00"`: false, "'\x00'": false, `"\x7f"`: false, "`\x7f`": false, `"a!"`: false, "#'a!'#": false, `"a b"`: false, `#"a b"#`: false, `"a\\b"`: false, "#\"a\\b\"#": false, "\"`a`\"": false, "#'\"a\"'#": false, `"\x80\x80"`: false, "#'\x80\x80'#": false, `"\xFFFD"`: false, "#'\xFFFD'#": false, } for path, isValid := range imports { t.Run(path, func(t *testing.T) { src := fmt.Sprintf("package p, import %s", path) _, err := ParseFile("", src) switch { case err != nil && isValid: t.Errorf("ParseFile(%s): got %v; expected no error", src, err) case err == nil && !isValid: t.Errorf("ParseFile(%s): got no error; expected one", src) } }) } } // TestIncompleteSelection ensures that an incomplete selector // expression is parsed as a (blank) *SelectorExpr, not a // *BadExpr. func TestIncompleteSelection(t *testing.T) { for _, src := range []string{ "{ a: fmt. }", // at end of object "{ a: fmt.\n0.0: x }", // not at end of struct } { t.Run("", func(t *testing.T) { f, err := ParseFile("", src) if err == nil { t.Fatalf("ParseFile(%s) succeeded unexpectedly", src) } const wantErr = "expected selector" if !strings.Contains(err.Error(), wantErr) { t.Errorf("ParseFile returned wrong error %q, want %q", err, wantErr) } var sel *ast.SelectorExpr ast.Walk(f, func(n ast.Node) bool { if n, ok := n.(*ast.SelectorExpr); ok { sel = n } return true }, nil) if sel == nil { t.Fatalf("found no *SelectorExpr: %#v %s", f.Decls[0], astinternal.DebugStr(f)) } const wantSel = "&{fmt _ {} {{}}}" if fmt.Sprint(sel) != wantSel { t.Fatalf("found selector %v, want %s", sel, wantSel) } }) } } // For debugging, do not delete. func TestX(t *testing.T) { t.Skip() f, err := ParseFile("input", ` `, ParseComments) if err != nil { t.Errorf("unexpected error: %v", err) } t.Error(astinternal.DebugStr(f)) } cue-lang-cue-db9cc73/cue/parser/performance_test.go000066400000000000000000000020071474664451600224360ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package parser import ( "os" "testing" ) var src = readFile("testdata/commas.src") func readFile(filename string) []byte { data, err := os.ReadFile(filename) if err != nil { panic(err) } return data } func BenchmarkParse(b *testing.B) { b.SetBytes(int64(len(src))) for i := 0; i < b.N; i++ { if _, err := ParseFile("", src, ParseComments); err != nil { b.Fatalf("benchmark failed due to parse error: %s", err) } } } cue-lang-cue-db9cc73/cue/parser/short_test.go000066400000000000000000000016131474664451600212760ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file contains test cases for short valid and invalid programs. package parser import "testing" var valids = []string{ "\n", `{}`, `{ [Name=_]: foo }`, `{ a: 3 }`, } func TestValid(t *testing.T) { for _, src := range valids { t.Run(src, func(t *testing.T) { checkErrors(t, src, src) }) } } cue-lang-cue-db9cc73/cue/parser/testdata/000077500000000000000000000000001474664451600203615ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/parser/testdata/commas.src000066400000000000000000000015061474664451600223530ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Test case for error messages/parser synchronization // after missing commas. package foo import "path/to/pkg" import name "path/to/pkg" foo: [ 0 // legal JSON ] bar: [ 0, 1, 2, 3 ] frontStyle: { "key": "value" , "key2": "value2" }cue-lang-cue-db9cc73/cue/parser/testdata/cue.mod/000077500000000000000000000000001474664451600217135ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/parser/testdata/cue.mod/module.cue000066400000000000000000000001121474664451600236700ustar00rootroot00000000000000Ensure that CUE files in Go testdata dirs are not part of the CUE module. cue-lang-cue-db9cc73/cue/path.go000066400000000000000000000466561474664451600165600ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "fmt" "math/bits" "strconv" "strings" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/literal" "cuelang.org/go/cue/parser" "cuelang.org/go/cue/token" "cuelang.org/go/internal/astinternal" "cuelang.org/go/internal/core/adt" "github.com/cockroachdb/apd/v3" ) // SelectorType represents the kind of a selector. It indicates both the label // type as well as whether it is a constraint or an actual value. type SelectorType uint16 const ( // StringLabel represents a regular non-definition field. StringLabel SelectorType = 1 << iota // IndexLabel represents a numeric index into an array. IndexLabel // DefinitionLabel represents a definition. DefinitionLabel // HiddenLabel represents a hidden non-definition field. HiddenLabel // HiddenDefinitionLabel represents a hidden definition. HiddenDefinitionLabel // OptionalConstraint represents an optional constraint (?). OptionalConstraint // RequiredConstraint represents a required constraint (!). RequiredConstraint // PatternConstraint represents a selector of fields in a struct // or array that match a constraint. PatternConstraint InvalidSelectorType SelectorType = 0 ) // fromArcType reports the constraint type for t. func fromArcType(t adt.ArcType) SelectorType { switch t { case adt.ArcMember: return 0 case adt.ArcOptional: return OptionalConstraint case adt.ArcRequired: return RequiredConstraint default: panic("arc type not supported") } } // LabelType reports the label type of t. func (t SelectorType) LabelType() SelectorType { return t & 0b0001_1111 } // ConstraintType reports the constraint type of t. func (t SelectorType) ConstraintType() SelectorType { return t & 0b1110_0000 } var selectorTypeStrings = [...]string{ "InvalidSelectorType", "StringLabel", "IndexLabel", "DefinitionLabel", "HiddenLabel", "HiddenDefinitionLabel", "OptionalConstraint", "RequiredConstraint", "PatternConstraint", } func (t SelectorType) String() string { if t.LabelType() == 0 && t.ConstraintType() == 0 { return "NoLabels" } single := bits.OnesCount16(uint16(t)) == 1 var buf strings.Builder for i := range selectorTypeStrings[:len(selectorTypeStrings)-1] { if t&(SelectorType(1)< 0 { buf.WriteByte('|') } buf.WriteString(selectorTypeStrings[i+1]) } return buf.String() } // IsHidden reports whether t describes a hidden field, regardless of // whether or not this is a constraint. func (t SelectorType) IsHidden() bool { t = t.LabelType() return t == HiddenLabel || t == HiddenDefinitionLabel } // IsDefinition reports whether t describes a definition, regardless of // whether or not this is a constraint. func (t SelectorType) IsDefinition() bool { t = t.LabelType() return t == HiddenDefinitionLabel || t == DefinitionLabel } // A Selector is a component of a path. type Selector struct { sel selector } // String reports the CUE representation of a selector. func (sel Selector) String() string { return sel.sel.String() } // Unquoted returns the unquoted value of a string label. // It panics unless [Selector.LabelType] is [StringLabel] and has a concrete name. func (sel Selector) Unquoted() string { if sel.LabelType() != StringLabel || sel.ConstraintType() >= PatternConstraint { panic("Selector.Unquoted invoked on non-string label") } switch s := sel.sel.(type) { case stringSelector: return string(s) case constraintSelector: return string(s.selector.(stringSelector)) } panic(fmt.Sprintf("unreachable %T", sel.sel)) } // IsConstraint reports whether s is optional or a pattern constraint. // Fields that are constraints are considered non-existing and their // values may be erroneous for a configuration to be valid.. func (sel Selector) IsConstraint() bool { return sel.Type().ConstraintType() != 0 } // IsString reports whether sel represents an optional, required, or regular // member field. func (sel Selector) IsString() bool { // TODO: consider deprecating this method. It is a bit wonkey now. t := sel.Type() t &^= OptionalConstraint | RequiredConstraint return t == StringLabel } // IsDefinition reports whether sel is a non-hidden definition and non-constraint label type. func (sel Selector) IsDefinition() bool { return sel.Type().IsDefinition() } // Type returns the type of the selector. func (sel Selector) Type() SelectorType { return sel.sel.labelType() | sel.sel.constraintType() } // LabelType returns the type of the label part of a selector. func (sel Selector) LabelType() SelectorType { return sel.sel.labelType() } // ConstraintType returns the type of the constraint part of a selector. func (sel Selector) ConstraintType() SelectorType { return sel.sel.constraintType() } // PkgPath reports the package path associated with a hidden label or "" if // this is not a hidden label. func (sel Selector) PkgPath() string { s, _ := sel.sel.(scopedSelector) return s.pkg } // Index returns the index of the selector. // It panics unless [Selector.Type] is [IndexLabel]. func (sel Selector) Index() int { // Note that lists will eventually have constraint types too, // and in that case sel.sel would be of type constraintSelector, // causing the type assertion below to fail. s, ok := sel.sel.(indexSelector) if !ok { panic("Index called on non-index selector") } return adt.Feature(s).Index() } var ( // AnyDefinition is a [Selector] which can be used to ask for any definition. // // In paths it is used to select constraints that apply to all elements. // AnyDefinition = anyDefinition anyDefinition = Selector{sel: anySelector(adt.AnyDefinition)} // AnyIndex is a [Selector] which can be used to ask for any index. // // In paths it is used to select constraints that apply to all elements. AnyIndex = anyIndex anyIndex = Selector{sel: anySelector(adt.AnyIndex)} // AnyString is a [Selector] which can be used to ask for any regular string field. // // In paths it is used to select constraints that apply to all elements. AnyString = anyString anyString = Selector{sel: anySelector(adt.AnyString)} ) // Optional converts sel into an optional constraint equivalent. // It's a no-op if the selector is already optional. // // foo -> foo? // foo! -> foo? func (sel Selector) Optional() Selector { return wrapConstraint(sel, OptionalConstraint) } // Required converts sel into a required constraint equivalent. // It's a no-op if the selector is already a required constraint. // // foo -> foo! // foo? -> foo! func (sel Selector) Required() Selector { return wrapConstraint(sel, RequiredConstraint) } type selector interface { String() string feature(ctx adt.Runtime) adt.Feature labelType() SelectorType constraintType() SelectorType isConstraint() bool } // A Path is series of selectors to query a CUE value. // The zero value corresponds to an empty path. type Path struct { path []Selector } // MakePath creates a Path from a sequence of selectors. func MakePath(selectors ...Selector) Path { return Path{path: selectors} } // pathToString is a utility function for creating debugging info. func pathToStrings(p Path) (a []string) { for _, sel := range p.Selectors() { a = append(a, sel.String()) } return a } // ParsePath parses a CUE expression into a Path. Any error resulting from // this conversion can be obtained by calling Err on the result. // // Unlike with normal CUE expressions, the first element of the path may be // a string literal. // // A path may not contain hidden fields. To create a path with hidden fields, // use MakePath and Ident. func ParsePath(s string) Path { if s == "" { return Path{} } expr, err := parser.ParseExpr("", s) if err != nil { return MakePath(Selector{pathError{errors.Promote(err, "invalid path")}}) } p := Path{path: toSelectors(expr)} for _, sel := range p.path { if sel.Type().IsHidden() { return MakePath(Selector{pathError{errors.Newf(token.NoPos, "invalid path: hidden fields not allowed in path %s", s)}}) } } return p } // Selectors reports the individual selectors of a path. func (p Path) Selectors() []Selector { return p.path } // String reports the CUE representation of p. func (p Path) String() string { if err := p.Err(); err != nil { return "_|_" } b := &strings.Builder{} for i, sel := range p.path { switch { case sel.Type() == IndexLabel: // TODO: use '.' in all cases, once supported. b.WriteByte('[') b.WriteString(sel.sel.String()) b.WriteByte(']') continue case i > 0: b.WriteByte('.') } b.WriteString(sel.sel.String()) } return b.String() } // Optional returns the optional form of a Path. For instance, // // foo.bar --> foo?.bar? func (p Path) Optional() Path { q := make([]Selector, 0, len(p.path)) for _, s := range p.path { q = appendSelector(q, wrapConstraint(s, OptionalConstraint)) } return Path{path: q} } func toSelectors(expr ast.Expr) []Selector { switch x := expr.(type) { case *ast.Ident: return []Selector{Label(x)} case *ast.BasicLit: return []Selector{basicLitSelector(x)} case *ast.IndexExpr: a := toSelectors(x.X) var sel Selector if b, ok := x.Index.(*ast.BasicLit); !ok { sel = Selector{pathError{ errors.Newf(token.NoPos, "non-constant expression %s", astinternal.DebugStr(x.Index))}} } else { sel = basicLitSelector(b) } return appendSelector(a, sel) case *ast.SelectorExpr: a := toSelectors(x.X) return appendSelector(a, Label(x.Sel)) default: return []Selector{{pathError{ errors.Newf(token.NoPos, "invalid label %s ", astinternal.DebugStr(x)), }}} } } // appendSelector is like append(a, sel), except that it collects errors // in a one-element slice. func appendSelector(a []Selector, sel Selector) []Selector { err, isErr := sel.sel.(pathError) if len(a) == 1 { if p, ok := a[0].sel.(pathError); ok { if isErr { p.Error = errors.Append(p.Error, err.Error) } return a } } if isErr { return []Selector{sel} } return append(a, sel) } func basicLitSelector(b *ast.BasicLit) Selector { switch b.Kind { case token.INT: var n literal.NumInfo if err := literal.ParseNum(b.Value, &n); err != nil { return Selector{pathError{ errors.Newf(token.NoPos, "invalid string index %s", b.Value), }} } var d apd.Decimal _ = n.Decimal(&d) i, err := d.Int64() if err != nil { return Selector{pathError{ errors.Newf(token.NoPos, "integer %s out of range", b.Value), }} } return Index(i) case token.STRING: info, _, _, _ := literal.ParseQuotes(b.Value, b.Value) if !info.IsDouble() { return Selector{pathError{ errors.Newf(token.NoPos, "invalid string index %s", b.Value)}} } s, _ := literal.Unquote(b.Value) return Selector{stringSelector(s)} default: return Selector{pathError{ errors.Newf(token.NoPos, "invalid literal %s", b.Value), }} } } // Label converts an AST label to a Selector. func Label(label ast.Label) Selector { switch x := label.(type) { case *ast.Ident: switch s := x.Name; { case strings.HasPrefix(s, "_"): // TODO: extract package from a bound identifier. return Selector{pathError{errors.Newf(token.NoPos, "invalid path: hidden label %s not allowed", s), }} case strings.HasPrefix(s, "#"): return Selector{definitionSelector(x.Name)} default: return Selector{stringSelector(x.Name)} } case *ast.BasicLit: return basicLitSelector(x) default: return Selector{pathError{ errors.Newf(token.NoPos, "invalid label %s ", astinternal.DebugStr(x)), }} } } // Err reports errors that occurred when generating the path. func (p Path) Err() error { var errs errors.Error for _, x := range p.path { if err, ok := x.sel.(pathError); ok { errs = errors.Append(errs, err.Error) } } return errs } func isHiddenOrDefinition(s string) bool { return strings.HasPrefix(s, "#") || strings.HasPrefix(s, "_") } // Hid returns a selector for a hidden field. It panics if pkg is empty. // Hidden fields are scoped by package, and pkg indicates for which package // the hidden field must apply. For anonymous packages, it must be set to "_". func Hid(name, pkg string) Selector { if !ast.IsValidIdent(name) { panic(fmt.Sprintf("invalid identifier %s", name)) } if !strings.HasPrefix(name, "_") { panic(fmt.Sprintf("%s is not a hidden field identifier", name)) } if pkg == "" { panic(fmt.Sprintf("missing package for hidden identifier %s", name)) } return Selector{scopedSelector{name, pkg}} } type scopedSelector struct { name, pkg string } // String returns the CUE representation of the definition. func (s scopedSelector) String() string { return s.name } func (scopedSelector) isConstraint() bool { return false } func (s scopedSelector) labelType() SelectorType { if strings.HasPrefix(s.name, "_#") { return HiddenDefinitionLabel } return HiddenLabel } func (s scopedSelector) constraintType() SelectorType { return 0 } func (s scopedSelector) feature(r adt.Runtime) adt.Feature { return adt.MakeIdentLabel(r, s.name, s.pkg) } // A Def marks a string as a definition label. An # will be added if a string is // not prefixed with a #. It will panic if s cannot be written as a valid // identifier. func Def(s string) Selector { if !strings.HasPrefix(s, "#") && !strings.HasPrefix(s, "_#") { s = "#" + s } if !ast.IsValidIdent(s) { panic(fmt.Sprintf("invalid definition %s", s)) } return Selector{definitionSelector(s)} } type definitionSelector string // String returns the CUE representation of the definition. func (d definitionSelector) String() string { return string(d) } func (d definitionSelector) isConstraint() bool { return false } func (d definitionSelector) labelType() SelectorType { return DefinitionLabel } func (s definitionSelector) constraintType() SelectorType { return 0 } func (d definitionSelector) feature(r adt.Runtime) adt.Feature { return adt.MakeIdentLabel(r, string(d), "") } // A Str is a CUE string label. Definition selectors are defined with Def. func Str(s string) Selector { return Selector{stringSelector(s)} } type stringSelector string func (s stringSelector) String() string { str := string(s) if isHiddenOrDefinition(str) || !ast.IsValidIdent(str) { return literal.Label.Quote(str) } return str } func (s stringSelector) isConstraint() bool { return false } func (s stringSelector) labelType() SelectorType { return StringLabel } func (s stringSelector) constraintType() SelectorType { return 0 } func (s stringSelector) feature(r adt.Runtime) adt.Feature { return adt.MakeStringLabel(r, string(s)) } // An Index selects a list element by index. // It returns an invalid selector if the index is out of range. func Index[T interface{ int | int64 }](x T) Selector { f, err := adt.MakeLabel(nil, int64(x), adt.IntLabel) if err != nil { return Selector{pathError{err}} } return Selector{indexSelector(f)} } type indexSelector adt.Feature func (s indexSelector) String() string { return strconv.Itoa(adt.Feature(s).Index()) } func (s indexSelector) labelType() SelectorType { return IndexLabel } func (s indexSelector) constraintType() SelectorType { return 0 } func (s indexSelector) isConstraint() bool { return false } func (s indexSelector) feature(r adt.Runtime) adt.Feature { return adt.Feature(s) } // an anySelector represents a wildcard option of a particular type. type anySelector adt.Feature func (s anySelector) String() string { return "[_]" } func (s anySelector) isConstraint() bool { return true } func (s anySelector) labelType() SelectorType { // FeatureTypes are numbered sequentially. SelectorType is a bitmap. As they // are defined in the same order, we can go from FeatureType to SelectorType // by left shifting. As valid FeatureTypes starts at 1, we need to end with // a final right shift. return SelectorType((1 << adt.Feature(s).Typ()) >> 1) } func (s anySelector) constraintType() SelectorType { return PatternConstraint } func (s anySelector) feature(r adt.Runtime) adt.Feature { return adt.Feature(s) } // TODO: allow import paths to be represented? // // // ImportPath defines a lookup at the root of an instance. It must be the first // // element of a Path. // // func ImportPath(s string) Selector { // return importSelector(s) // } type constraintSelector struct { selector constraint SelectorType } func (s constraintSelector) labelType() SelectorType { return s.selector.labelType() } func (s constraintSelector) constraintType() SelectorType { return s.constraint } func wrapConstraint(s Selector, t SelectorType) Selector { sel := s.sel if c, ok := sel.(constraintSelector); ok { if c.constraint == t { return s } sel = c.selector // unwrap } return Selector{constraintSelector{sel, t}} } // func isOptional(sel selector) bool { // _, ok := sel.(optionalSelector) // return ok // } func (s constraintSelector) isConstraint() bool { return true } func (s constraintSelector) String() string { var suffix string switch s.constraint { case OptionalConstraint: suffix = "?" case RequiredConstraint: suffix = "!" } return s.selector.String() + suffix } // TODO: allow looking up in parent scopes? // // Parent returns a Selector for looking up in the parent of a current node. // // Parent selectors may only occur at the start of a Path. // func Parent() Selector { // return parentSelector{} // } // type parentSelector struct{} // func (p parentSelector) String() string { return "__up" } // func (p parentSelector) feature(r adt.Runtime) adt.Feature { // return adt.InvalidLabel // } type pathError struct { errors.Error } func (p pathError) String() string { return "" } func (p pathError) isConstraint() bool { return false } func (p pathError) labelType() SelectorType { return InvalidSelectorType } func (p pathError) constraintType() SelectorType { return 0 } func (p pathError) feature(r adt.Runtime) adt.Feature { return adt.InvalidLabel } func valueToSel(v adt.Value) Selector { switch x := adt.Unwrap(v).(type) { case *adt.Num: i, err := x.X.Int64() if err != nil { return Selector{&pathError{errors.Promote(err, "invalid number")}} } return Index(i) case *adt.String: return Str(x.Str) default: return Selector{pathError{errors.Newf(token.NoPos, "dynamic selector")}} } } func featureToSel(f adt.Feature, r adt.Runtime) Selector { switch f.Typ() { case adt.StringLabel: return Str(f.StringValue(r)) case adt.IntLabel: return Index(f.Index()) case adt.DefinitionLabel: return Def(f.IdentString(r)) case adt.HiddenLabel, adt.HiddenDefinitionLabel: ident := f.IdentString(r) pkg := f.PkgID(r) return Hid(ident, pkg) } return Selector{pathError{ errors.Newf(token.NoPos, "unexpected feature type %v", f.Typ()), }} } func featureToSelType(f adt.Feature, at adt.ArcType) (st SelectorType) { switch f.Typ() { case adt.StringLabel: st = StringLabel case adt.IntLabel: st = IndexLabel case adt.DefinitionLabel: st = DefinitionLabel case adt.HiddenLabel: st = HiddenLabel case adt.HiddenDefinitionLabel: st = HiddenDefinitionLabel default: panic("unsupported arc type") } return st | fromArcType(at) } cue-lang-cue-db9cc73/cue/path_test.go000066400000000000000000000210331474664451600175750ustar00rootroot00000000000000// Copyright 2020 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "fmt" "testing" "cuelang.org/go/cue" "cuelang.org/go/internal/cuetdtest" ) func TestPaths(t *testing.T) { type testCase struct { path cue.Path out string str string err bool } testCases := []testCase{{ path: cue.MakePath(cue.Str("list"), cue.AnyIndex), out: "int", str: "list.[_]", }, { path: cue.MakePath(cue.Def("#Foo"), cue.Str("a"), cue.Str("b")), out: "1", str: "#Foo.a.b", }, { path: cue.ParsePath(`#Foo.a.b`), out: "1", str: "#Foo.a.b", }, { path: cue.ParsePath(`"#Foo".c.d`), out: "2", str: `"#Foo".c.d`, }, { // fallback Def(Foo) -> Def(#Foo) path: cue.MakePath(cue.Def("Foo"), cue.Str("a"), cue.Str("b")), out: "1", str: "#Foo.a.b", }, { path: cue.MakePath(cue.Str("b"), cue.Index(2)), out: "6", str: "b[2]", // #Foo.b.2 }, { path: cue.MakePath(cue.Str("c"), cue.Str("#Foo")), out: "7", str: `c."#Foo"`, }, { path: cue.MakePath(cue.Hid("_foo", "_"), cue.Str("b")), out: "5", str: `_foo.b`, }, { path: cue.ParsePath("#Foo.a.b"), str: "#Foo.a.b", out: "1", }, { path: cue.ParsePath("#Foo.a.c"), str: "#Foo.a.c", out: `_|_ // field not found: c`, }, { path: cue.ParsePath(`b[2]`), str: `b[2]`, out: "6", }, { path: cue.ParsePath(`c."#Foo"`), str: `c."#Foo"`, out: "7", }, { path: cue.ParsePath("foo._foo"), str: "_|_", err: true, out: `_|_ // invalid path: hidden label _foo not allowed`, }, { path: cue.ParsePath(`c."#Foo`), str: "_|_", err: true, out: `_|_ // string literal not terminated`, }, { path: cue.ParsePath(`b[a]`), str: "_|_", err: true, out: `_|_ // non-constant expression a`, }, { path: cue.ParsePath(`b['1']`), str: "_|_", err: true, out: `_|_ // invalid string index '1'`, }, { path: cue.ParsePath(`b[3T]`), str: "_|_", err: true, out: `_|_ // int label out of range (3000000000000 not >=0 and <= 268435454)`, }, { path: cue.ParsePath(`b[3.3]`), str: "_|_", err: true, out: `_|_ // invalid literal 3.3`, }, { path: cue.MakePath(cue.Str("map"), cue.AnyString), out: "int", str: "map.[_]", }, { path: cue.MakePath(cue.Str("list"), cue.AnyIndex), out: "int", str: "list.[_]", }, { path: cue.ParsePath("x.y"), out: "{\n\tb: 0\n}", str: "x.y", }, { path: cue.ParsePath("x.y.b"), out: "0", str: "x.y.b", }, { // Issue 3577 path: cue.ParsePath("pkg.y"), out: `"hello"`, str: "pkg.y", // show original path, not structure shared path. }} cuetdtest.Run(t, testCases, func(t *cuetdtest.T, tc *testCase) { ctx := t.M.CueContext() val := mustCompile(t, ctx, ` #Foo: a: b: 1 "#Foo": c: d: 2 _foo: b: 5 a: 3 b: [4, 5, 6] c: "#Foo": 7 map: [string]: int list: [...int] // Issue 2060 let X = {a: b: 0} x: y: X.a // Issue 3577 pkg: z z: y: "hello" `) t.Equal(tc.path.Err() != nil, tc.err) w := val.LookupPath(tc.path) t.Equal(fmt.Sprint(w), tc.out) if w.Err() != nil { return } t.Equal(w.Path().String(), tc.str) }) } var selectorTests = []struct { sel cue.Selector stype cue.SelectorType string string unquoted string index int isHidden bool isConstraint bool isDefinition bool isString bool pkgPath string }{{ sel: cue.Str("foo"), stype: cue.StringLabel, string: "foo", unquoted: "foo", isString: true, }, { sel: cue.Str("_foo"), stype: cue.StringLabel, string: `"_foo"`, unquoted: "_foo", isString: true, }, { sel: cue.Str(`a "b`), stype: cue.StringLabel, string: `"a \"b"`, unquoted: `a "b`, isString: true, }, { sel: cue.Index(5), stype: cue.IndexLabel, string: "5", index: 5, }, { sel: cue.Def("foo"), stype: cue.DefinitionLabel, string: "#foo", isDefinition: true, }, { sel: cue.Str("foo").Optional(), stype: cue.StringLabel | cue.OptionalConstraint, string: "foo?", unquoted: "foo", isString: true, isConstraint: true, }, { sel: cue.Str("foo").Required(), stype: cue.StringLabel | cue.RequiredConstraint, string: "foo!", unquoted: "foo", isString: true, isConstraint: true, }, { sel: cue.Def("foo").Required().Optional(), stype: cue.DefinitionLabel | cue.OptionalConstraint, string: "#foo?", isDefinition: true, isConstraint: true, }, { sel: cue.Def("foo").Optional().Required(), stype: cue.DefinitionLabel | cue.RequiredConstraint, string: "#foo!", isDefinition: true, isConstraint: true, }, { sel: cue.AnyString, stype: cue.StringLabel | cue.PatternConstraint, string: "[_]", isConstraint: true, }, { sel: cue.AnyIndex, stype: cue.IndexLabel | cue.PatternConstraint, string: "[_]", isConstraint: true, }, { sel: cue.Hid("_foo", "example.com"), stype: cue.HiddenLabel, string: "_foo", isHidden: true, pkgPath: "example.com", }, { sel: cue.Hid("_#foo", "example.com"), stype: cue.HiddenDefinitionLabel, string: "_#foo", isHidden: true, isDefinition: true, pkgPath: "example.com", }} func TestSelector(t *testing.T) { for _, tc := range selectorTests { t.Run(tc.sel.String(), func(t *testing.T) { sel := tc.sel if got, want := sel.Type(), tc.stype; got != want { t.Errorf("unexpected type; got %v want %v", got, want) } if got, want := sel.String(), tc.string; got != want { t.Errorf("unexpected sel.String result; got %q want %q", got, want) } if tc.unquoted == "" { checkPanic(t, "Selector.Unquoted invoked on non-string label", func() { sel.Unquoted() }) } else { if got, want := sel.Unquoted(), tc.unquoted; got != want { t.Errorf("unexpected sel.Unquoted result; got %q want %q", got, want) } } if sel.Type() != cue.IndexLabel { checkPanic(t, "Index called on non-index selector", func() { sel.Index() }) } else { if got, want := sel.Index(), tc.index; got != want { t.Errorf("unexpected sel.Index result; got %v want %v", got, want) } } if got, want := sel.Type().IsHidden(), tc.isHidden; got != want { t.Errorf("unexpected sel.IsHidden result; got %v want %v", got, want) } if got, want := sel.IsConstraint(), tc.isConstraint; got != want { t.Errorf("unexpected sel.IsOptional result; got %v want %v", got, want) } if got, want := sel.IsString(), tc.isString; got != want { t.Errorf("unexpected sel.IsString result; got %v want %v", got, want) } if got, want := sel.IsDefinition(), tc.isDefinition; got != want { t.Errorf("unexpected sel.IsDefinition result; got %v want %v", got, want) } if got, want := sel.PkgPath(), tc.pkgPath; got != want { t.Errorf("unexpected sel.PkgPath result; got %v want %v", got, want) } }) } } func TestSelectorTypeString(t *testing.T) { if got, want := cue.InvalidSelectorType.String(), "NoLabels"; got != want { t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) } if got, want := cue.PatternConstraint.String(), "PatternConstraint"; got != want { t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) } if got, want := (cue.StringLabel | cue.OptionalConstraint).String(), "StringLabel|OptionalConstraint"; got != want { t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) } if got, want := cue.SelectorType(255).String(), "StringLabel|IndexLabel|DefinitionLabel|HiddenLabel|HiddenDefinitionLabel|OptionalConstraint|RequiredConstraint|PatternConstraint"; got != want { t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) } } func checkPanic(t *testing.T, wantPanicStr string, f func()) { gotPanicStr := "" func() { defer func() { e := recover() if e == nil { t.Errorf("function did not panic") return } gotPanicStr = fmt.Sprint(e) }() f() }() if got, want := gotPanicStr, wantPanicStr; got != want { t.Errorf("unexpected panic message; got %q want %q", got, want) } } cue-lang-cue-db9cc73/cue/query.go000066400000000000000000000044051474664451600167530ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "cuelang.org/go/internal/core/adt" ) // This file contains query-related code. // getScopePrefix finds the Vertex that exists in v for the longest prefix of p. // // It is used to make the parent scopes visible when resolving expressions. func getScopePrefix(v Value, p Path) Value { for _, sel := range p.Selectors() { w := v.LookupPath(MakePath(sel)) if !w.Exists() { break } v = w } return v } // LookupPath reports the value for path p relative to v. // // Use [AnyString] and [AnyIndex] to find the value of undefined element types // for structs and lists respectively, for example for the patterns in // `{[string]: int}` and `[...string]`. func (v Value) LookupPath(p Path) Value { if v.v == nil { return Value{} } n := v.v parent := v.parent_ ctx := v.ctx() outer: for _, sel := range p.path { f := sel.sel.feature(v.idx) deref := n.DerefValue() for _, a := range deref.Arcs { if a.Label == f { if a.IsConstraint() && !sel.sel.isConstraint() { break } parent = linkParent(parent, n, a) n = a continue outer } } if sel.sel.isConstraint() { x := &adt.Vertex{ Parent: n, Label: sel.sel.feature(ctx), } n.MatchAndInsert(ctx, x) if x.HasConjuncts() { x.Finalize(ctx) parent = linkParent(parent, n, x) n = x continue } } var x *adt.Bottom if err, ok := sel.sel.(pathError); ok { x = &adt.Bottom{Err: err.Error} } else { x = mkErr(n, adt.EvalError, "field not found: %v", sel.sel) if n.Accept(ctx, f) { x.Code = adt.IncompleteError } x.NotExists = true } v := makeValue(v.idx, n, parent) return newErrValue(v, x) } return makeValue(v.idx, n, parent) } cue-lang-cue-db9cc73/cue/query_test.go000066400000000000000000000074611474664451600200170ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "bytes" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/internal/cuetxtar" "cuelang.org/go/internal/diff" "golang.org/x/tools/txtar" ) func TestLookupPath(t *testing.T) { ctx := cuecontext.New() testCases := []struct { in string path cue.Path out string `test:"update"` // :nerdSnipe: err string `test:"update"` // :nerdSnipe: }{{ in: ` #V: { x: int } #X: { [string]: int64 } & #V v: #X `, path: cue.ParsePath("v.x"), out: `int64`, }, { in: `#foo: 3`, path: cue.ParsePath("#foo"), out: `3`, }, { in: `_foo: 3`, path: cue.MakePath(cue.Def("_foo")), err: `field not found: #_foo`, }, { in: `_#foo: 3`, path: cue.MakePath(cue.Def("_#foo")), err: `field not found: _#foo`, }, { in: `"foo", #foo: 3`, path: cue.ParsePath("#foo"), out: `3`, }, { in: ` a: [...int] `, path: cue.MakePath(cue.Str("a"), cue.AnyIndex), out: `int`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.AnyString, cue.Str("a")), out: `string`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.Str("b").Optional(), cue.Str("a")), out: `"b"`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.AnyString), out: `{a: string}`, }, { in: ` a: [Foo=string]: [Bar=string]: { b: Foo+Bar } `, path: cue.MakePath(cue.Str("a"), cue.Str("b"), cue.Str("c")).Optional(), out: `{b: "bc"}`, }, { in: ` a: [Foo=string]: b: [Bar=string]: { c: Foo } a: foo: b: [Bar=string]: { d: Bar } `, path: cue.MakePath(cue.Str("a"), cue.Str("foo"), cue.Str("b"), cue.AnyString), out: `{c: "foo", d: string}`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.Str("a")), err: `field not found: a`, }} for _, tc := range testCases { t.Run(tc.path.String(), func(t *testing.T) { v := mustCompile(t, ctx, tc.in) v = v.LookupPath(tc.path) if err := v.Err(); err != nil || tc.err != "" { if got := err.Error(); got != tc.err { t.Errorf("error: got %v; want %v", got, tc.err) } } if exists := v.Exists(); exists != (tc.err == "") { t.Fatalf("exists: got %v; want: %v", exists, tc.err == "") } else if !exists { return } w := mustCompile(t, ctx, tc.out) if k, d := diff.Diff(v, w); k != diff.Identity { b := &bytes.Buffer{} diff.Print(b, d) t.Error(b) } }) } } func TestHidden(t *testing.T) { in := ` -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- import "mod.test/foo" a: foo.C b: _c _c: 2 -- foo/foo.cue -- package foo C: _d _d: 3 ` a := txtar.Parse([]byte(in)) instance := cuetxtar.Load(a, t.TempDir())[0] if instance.Err != nil { t.Fatal(instance.Err) } v := cuecontext.New().BuildInstance(instance) testCases := []struct { path cue.Path pkg string }{{ path: cue.ParsePath("a"), pkg: "mod.test/foo", }, { path: cue.ParsePath("b"), pkg: "_", }} for _, tc := range testCases { t.Run(tc.path.String(), func(t *testing.T) { v := v.LookupPath(tc.path) p := cue.Dereference(cue.Dereference(v)).Path().Selectors() if got := p[len(p)-1].PkgPath(); got != tc.pkg { t.Errorf("got %v; want %v", got, tc.pkg) } }) } } cue-lang-cue-db9cc73/cue/resolve_test.go000066400000000000000000000013731474664451600203250ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "strings" "testing" ) func TestX(t *testing.T) { // Don't remove. For debugging. in := ` ` if strings.TrimSpace(in) == "" { t.Skip() } } cue-lang-cue-db9cc73/cue/scanner/000077500000000000000000000000001474664451600167055ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/scanner/scanner.go000066400000000000000000000521441474664451600206730ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package scanner implements a scanner for CUE source text. It takes a []byte // as source which can then be tokenized through repeated calls to the Scan // method. package scanner import ( "fmt" "path/filepath" "unicode" "unicode/utf8" "cuelang.org/go/cue/token" ) // An ErrorHandler is a generic error handler used throughout CUE packages. // // The position points to the beginning of the offending value. type ErrorHandler func(pos token.Pos, msg string, args []interface{}) // A Scanner holds the Scanner's internal state while processing // a given text. It can be allocated as part of another data // structure but must be initialized via Init before use. type Scanner struct { // immutable state file *token.File // source file handle dir string // directory portion of file.Name() src []byte // source errh ErrorHandler // error reporting; or nil mode Mode // scanning mode // scanning state ch rune // current character offset int // character offset rdOffset int // reading offset (position after current character) linesSinceLast int spacesSinceLast int insertEOL bool // insert a comma before next newline quoteStack []quoteInfo // public state - ok to modify ErrorCount int // number of errors encountered } type quoteInfo struct { char rune numChar int numHash int } const bom = 0xFEFF // byte order mark, only permitted as very first character // Read the next Unicode char into s.ch. // s.ch < 0 means end-of-file. func (s *Scanner) next() { if s.rdOffset < len(s.src) { s.offset = s.rdOffset if s.ch == '\n' { s.file.AddLine(s.offset) } r, w := rune(s.src[s.rdOffset]), 1 switch { case r == 0: s.errf(s.offset, "illegal character NUL") case r >= utf8.RuneSelf: // not ASCII r, w = utf8.DecodeRune(s.src[s.rdOffset:]) if r == utf8.RuneError && w == 1 { s.errf(s.offset, "illegal UTF-8 encoding") } else if r == bom && s.offset > 0 { s.errf(s.offset, "illegal byte order mark") } } s.rdOffset += w s.ch = r } else { s.offset = len(s.src) if s.ch == '\n' { s.file.AddLine(s.offset) } s.ch = -1 // eof } } // A Mode value is a set of flags (or 0). // They control scanner behavior. type Mode uint // These constants are options to the Init function. const ( ScanComments Mode = 1 << iota // return comments as COMMENT tokens DontInsertCommas // do not automatically insert commas ) // Init prepares the scanner s to tokenize the text src by setting the // scanner at the beginning of src. The scanner uses the file set file // for position information and it adds line information for each line. // It is ok to re-use the same file when re-scanning the same file as // line information which is already present is ignored. Init causes a // panic if the file size does not match the src size. // // Calls to Scan will invoke the error handler err if they encounter a // syntax error and err is not nil. Also, for each error encountered, // the Scanner field ErrorCount is incremented by one. The mode parameter // determines how comments are handled. // // Note that Init may call err if there is an error in the first character // of the file. func (s *Scanner) Init(file *token.File, src []byte, eh ErrorHandler, mode Mode) { // Explicitly initialize all fields since a scanner may be reused. if file.Size() != len(src) { panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src))) } s.file = file s.dir, _ = filepath.Split(file.Name()) s.src = src s.errh = eh s.mode = mode s.ch = ' ' s.offset = 0 s.rdOffset = 0 s.insertEOL = false s.ErrorCount = 0 s.next() if s.ch == bom { s.next() // ignore BOM at file beginning } } func (s *Scanner) errf(offs int, msg string, args ...interface{}) { if s.errh != nil { s.errh(s.file.Pos(offs, 0), msg, args) } s.ErrorCount++ } func (s *Scanner) scanComment() string { // initial '/' already consumed; s.ch == '/' offs := s.offset - 1 // position of initial '/' hasCR := false if s.ch == '/' { //-style comment s.next() for s.ch != '\n' && s.ch >= 0 { if s.ch == '\r' { hasCR = true } s.next() } goto exit } s.errf(offs, "comment not terminated") exit: lit := s.src[offs:s.offset] if hasCR { // TODO: preserve /r/n lit = stripCR(lit) } return string(lit) } func isLetter(ch rune) bool { return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch >= utf8.RuneSelf && unicode.IsLetter(ch) } func isDigit(ch rune) bool { // TODO(mpvl): Is this correct? return '0' <= ch && ch <= '9' || ch >= utf8.RuneSelf && unicode.IsDigit(ch) } func (s *Scanner) scanFieldIdentifier() string { offs := s.offset if s.ch == '_' { s.next() } if s.ch == '#' { s.next() // TODO: remove this block to allow # if isDigit(s.ch) { return string(s.src[offs:s.offset]) } } for isLetter(s.ch) || isDigit(s.ch) || s.ch == '_' || s.ch == '$' { s.next() } return string(s.src[offs:s.offset]) } func (s *Scanner) scanIdentifier() string { offs := s.offset for isLetter(s.ch) || isDigit(s.ch) || s.ch == '_' || s.ch == '$' { s.next() } return string(s.src[offs:s.offset]) } func digitVal(ch rune) int { switch { case '0' <= ch && ch <= '9': return int(ch - '0') case ch == '_': return 0 case 'a' <= ch && ch <= 'f': return int(ch - 'a' + 10) case 'A' <= ch && ch <= 'F': return int(ch - 'A' + 10) } return 16 // larger than any legal digit val } func (s *Scanner) scanMantissa(base int) { var last rune for digitVal(s.ch) < base { if last == '_' && s.ch == '_' { s.errf(s.offset, "illegal '_' in number") } last = s.ch s.next() } if last == '_' { s.errf(s.offset-1, "illegal '_' in number") } } func (s *Scanner) scanNumber(seenDecimalPoint bool) (token.Token, string) { // digitVal(s.ch) < 10 offs := s.offset tok := token.INT if seenDecimalPoint { offs-- tok = token.FLOAT s.scanMantissa(10) goto exponent } if s.ch == '0' { // int or float offs := s.offset s.next() if s.ch == 'x' || s.ch == 'X' { // hexadecimal int s.next() s.scanMantissa(16) if s.offset-offs <= 2 { // only scanned "0x" or "0X" s.errf(offs, "illegal hexadecimal number") } } else if s.ch == 'b' { // binary int s.next() s.scanMantissa(2) if s.offset-offs <= 2 { // only scanned "0b" s.errf(offs, "illegal binary number") } } else if s.ch == 'o' { // octal int s.next() s.scanMantissa(8) if s.offset-offs <= 2 { // only scanned "0o" s.errf(offs, "illegal octal number") } } else { // 0 or float seenDigits := false if s.ch >= '0' && s.ch <= '9' { seenDigits = true s.scanMantissa(10) } if s.ch == '.' || s.ch == 'e' || s.ch == 'E' { goto fraction } if seenDigits { // integer other than 0 may not start with 0 s.errf(offs, "illegal integer number") } } goto exit } // decimal int or float s.scanMantissa(10) // TODO: allow 3h4s, etc. // switch s.ch { // case 'h', 'm', 's', "µ"[0], 'u', 'n': // } fraction: if s.ch == '.' { if p := s.offset + 1; p < len(s.src) && s.src[p] == '.' { // interpret dot as part of a range. goto exit } tok = token.FLOAT s.next() s.scanMantissa(10) } exponent: switch s.ch { case 'K', 'M', 'G', 'T', 'P': tok = token.INT // TODO: Or should we allow this to be a float? s.next() if s.ch == 'i' { s.next() } goto exit } if s.ch == 'e' || s.ch == 'E' { tok = token.FLOAT s.next() if s.ch == '-' || s.ch == '+' { s.next() } s.scanMantissa(10) } exit: return tok, string(s.src[offs:s.offset]) } // scanEscape parses an escape sequence where rune is the accepted // escaped quote. In case of a syntax error, it stops at the offending // character (without consuming it) and returns false. Otherwise // it returns true. // // Must be compliant with https://tools.ietf.org/html/rfc4627. func (s *Scanner) scanEscape(quote quoteInfo) (ok, interpolation bool) { for range quote.numHash { if s.ch != '#' { return true, false } s.next() } offs := s.offset var n int var base, max uint32 switch s.ch { case '(': return true, true case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '/', quote.char: s.next() return true, false case '0', '1', '2', '3', '4', '5', '6', '7': n, base, max = 3, 8, 255 case 'x': s.next() n, base, max = 2, 16, 255 case 'u': s.next() n, base, max = 4, 16, unicode.MaxRune case 'U': s.next() n, base, max = 8, 16, unicode.MaxRune default: msg := "unknown escape sequence" if s.ch < 0 { msg = "escape sequence not terminated" } s.errf(offs, msg) return false, false } var x uint32 for n > 0 { d := uint32(digitVal(s.ch)) if d >= base { if s.ch < 0 { s.errf(s.offset, "escape sequence not terminated") } else { s.errf(s.offset, "illegal character %#U in escape sequence", s.ch) } return false, false } x = x*base + d s.next() n-- } // TODO: this is valid JSON, so remove, but normalize and report an error // if for unmatched surrogate pairs . if x > max { s.errf(offs, "escape sequence is invalid Unicode code point") return false, false } return true, false } func (s *Scanner) scanString(offs int, quote quoteInfo) (token.Token, string) { // ", """, ', or ''' opening already consumed tok := token.STRING hasCR := false extra := 0 for { ch := s.ch if (quote.numChar != 3 && ch == '\n') || ch < 0 { s.errf(offs, "string literal not terminated") lit := s.src[offs:s.offset] if hasCR { lit = stripCR(lit) } return tok, string(lit) } s.next() ch, ok := s.consumeStringClose(ch, quote) if ok { break } if ch == '\r' && quote.numChar == 3 { hasCR = true } if ch == '\\' { if _, interpolation := s.scanEscape(quote); interpolation { tok = token.INTERPOLATION extra = 1 s.quoteStack = append(s.quoteStack, quote) break } } } lit := s.src[offs : s.offset+extra] if hasCR { lit = stripCR(lit) } return tok, string(lit) } func (s *Scanner) consumeQuotes(quote rune, max int) (next rune, n int) { for ; n < max; n++ { if s.ch != quote { return s.ch, n } s.next() } return s.ch, n } func (s *Scanner) consumeStringClose(ch rune, quote quoteInfo) (next rune, atEnd bool) { if quote.char != ch { return ch, false } numChar := quote.numChar n := numChar + quote.numHash want := quote.char for i := 1; i < n; i++ { if i == numChar { want = '#' } if want != s.ch { return ch, false } ch = s.ch s.next() } return s.ch, true } func (s *Scanner) scanHashes(maxHash int) int { for i := range maxHash { if s.ch != '#' { return i } s.next() } return maxHash } func stripCR(b []byte) []byte { c := make([]byte, len(b)) i := 0 for _, ch := range b { if ch != '\r' { c[i] = ch i++ } } return c[:i] } // scanAttribute scans aa full attribute of the form @foo(str). An attribute // is a lexical entry and as such whitespace is treated as normal characters // within the attribute. func (s *Scanner) scanAttribute() (tok token.Token, lit string) { offs := s.offset - 1 // @ already consumed s.scanIdentifier() if _, tok, _ := s.Scan(); tok == token.LPAREN { s.scanAttributeTokens(token.RPAREN) } else { s.errf(s.offset, "invalid attribute: expected '('") } return token.ATTRIBUTE, string(s.src[offs:s.offset]) } func (s *Scanner) scanAttributeTokens(close token.Token) { for { switch _, tok, _ := s.Scan(); tok { case close: return case token.EOF: s.errf(s.offset, "attribute missing '%s'", close) return case token.INTERPOLATION: s.errf(s.offset, "interpolation not allowed in attribute") s.popInterpolation() s.recoverParen(1) case token.LPAREN: s.scanAttributeTokens(token.RPAREN) case token.LBRACE: s.scanAttributeTokens(token.RBRACE) case token.LBRACK: s.scanAttributeTokens(token.RBRACK) case token.RPAREN, token.RBRACK, token.RBRACE: s.errf(s.offset, "unexpected '%s'", tok) } } } // recoverParen is an approximate recovery mechanism to recover from invalid // attributes. func (s *Scanner) recoverParen(open int) { for { switch s.ch { case '\n', -1: return case '(': open++ case ')': if open--; open == 0 { return } } s.next() } } func (s *Scanner) skipWhitespace(inc int) { for { switch s.ch { case ' ', '\t': s.spacesSinceLast += inc case '\n': s.linesSinceLast += inc if s.insertEOL { return } case '\r': default: return } s.next() } } // Helper functions for scanning multi-byte tokens such as >> += >>= . // Different routines recognize different length tok_i based on matches // of ch_i. If a token ends in '=', the result is tok1 or tok3 // respectively. Otherwise, the result is tok0 if there was no other // matching character, or tok2 if the matching character was ch2. func (s *Scanner) switch2(tok0, tok1 token.Token) token.Token { if s.ch == '=' { s.next() return tok1 } return tok0 } func (s *Scanner) popInterpolation() quoteInfo { quote := s.quoteStack[len(s.quoteStack)-1] s.quoteStack = s.quoteStack[:len(s.quoteStack)-1] return quote } // ResumeInterpolation resumes scanning of a string interpolation. func (s *Scanner) ResumeInterpolation() string { quote := s.popInterpolation() _, str := s.scanString(s.offset-1, quote) return str } // Offset returns the current position offset. func (s *Scanner) Offset() int { return s.offset } // Scan scans the next token and returns the token position, the token, // and its literal string if applicable. The source end is indicated by // EOF. // // If the returned token is a literal (IDENT, INT, FLOAT, // IMAG, CHAR, STRING) or COMMENT, the literal string // has the corresponding value. // // If the returned token is a keyword, the literal string is the keyword. // // If the returned token is Comma, the corresponding // literal string is "," if the comma was present in the source, // and "\n" if the semicolon was inserted because of a newline or // at EOF. // // If the returned token is ILLEGAL, the literal string is the // offending character. // // In all other cases, Scan returns an empty literal string. // // For more tolerant parsing, Scan will return a valid token if // possible even if a syntax error was encountered. Thus, even // if the resulting token sequence contains no illegal tokens, // a client may not assume that no error occurred. Instead it // must check the scanner's ErrorCount or the number of calls // of the error handler, if there was one installed. // // Scan adds line information to the file added to the file // set with Init. Token positions are relative to that file // and thus relative to the file set. func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) { scanAgain: s.skipWhitespace(1) var rel token.RelPos switch { case s.linesSinceLast > 1: rel = token.NewSection case s.linesSinceLast == 1: rel = token.Newline case s.spacesSinceLast > 0: rel = token.Blank default: rel = token.NoSpace } // current token start offset := s.offset pos = s.file.Pos(offset, rel) // determine token value insertEOL := false var quote quoteInfo switch ch := s.ch; { case '0' <= ch && ch <= '9': insertEOL = true tok, lit = s.scanNumber(false) case isLetter(ch), ch == '$', ch == '#': lit = s.scanFieldIdentifier() if len(lit) > 1 { // keywords are longer than one letter - avoid lookup otherwise tok = token.Lookup(lit) insertEOL = true break } if ch != '#' || (s.ch != '\'' && s.ch != '"' && s.ch != '#') { tok = token.IDENT insertEOL = true break } quote.numHash = 1 ch = s.ch fallthrough default: s.next() // always make progress switch ch { case -1: if s.insertEOL { s.insertEOL = false // EOF consumed return s.file.Pos(offset, token.Elided), token.COMMA, "\n" } tok = token.EOF case '_': if s.ch == '|' { // Unconditionally require this to be followed by another // underscore to avoid needing an extra lookahead. // Note that `_|x` is always equal to _. s.next() if s.ch != '_' { s.errf(s.file.Offset(pos), "illegal token '_|'; expected '_'") insertEOL = s.insertEOL // preserve insertComma info tok = token.ILLEGAL lit = "_|" break } s.next() tok = token.BOTTOM lit = "_|_" } else { tok = token.IDENT lit = "_" + s.scanFieldIdentifier() } insertEOL = true case '\n': // we only reach here if s.insertComma was // set in the first place and exited early // from s.skipWhitespace() s.insertEOL = false // newline consumed p := s.file.Pos(offset, token.Elided) s.skipWhitespace(1) // Don't elide comma before a ',' or ':' to ensure JSON // conformance. Note that cue fmt should immediately undo those. if s.ch == ',' || s.ch == ':' { return s.Scan() } return p, token.COMMA, "\n" case '#': for quote.numHash++; s.ch == '#'; quote.numHash++ { s.next() } ch = s.ch if ch != '\'' && ch != '"' { break } s.next() fallthrough case '"', '\'': insertEOL = true quote.char = ch quote.numChar = 1 offs := s.offset - 1 - quote.numHash switch _, n := s.consumeQuotes(ch, 2); n { case 0: quote.numChar = 1 tok, lit = s.scanString(offs, quote) case 1: // When the string is surrounded by hashes, // a single leading quote is OK (and part of the string) // e.g. #""hello""# // unless it's succeeded by the correct number of terminating // hash characters // e.g. ##""## if n := s.scanHashes(quote.numHash); n == quote.numHash { // It's the empty string. tok, lit = token.STRING, string(s.src[offs:s.offset]) } else { tok, lit = s.scanString(offs, quote) } case 2: quote.numChar = 3 switch s.ch { case '\n': s.next() tok, lit = s.scanString(offs, quote) case '\r': s.next() if s.ch == '\n' { s.next() tok, lit = s.scanString(offs, quote) break } fallthrough default: s.errf(offs, "expected newline after multiline quote %s", s.src[offs:s.offset]) tok, lit = token.STRING, string(s.src[offs:s.offset]) } } case '@': insertEOL = true tok, lit = s.scanAttribute() case ':': tok = token.COLON case ';': tok = token.SEMICOLON insertEOL = true case '?': tok = token.OPTION insertEOL = true case '.': if '0' <= s.ch && s.ch <= '9' { insertEOL = true tok, lit = s.scanNumber(true) } else if s.ch == '.' { s.next() if s.ch == '.' { s.next() tok = token.ELLIPSIS insertEOL = true } else { s.errf(s.file.Offset(pos), "illegal token '..'; expected '.'") } } else { tok = token.PERIOD } case ',': tok = token.COMMA lit = "," case '(': tok = token.LPAREN case ')': insertEOL = true tok = token.RPAREN case '[': tok = token.LBRACK case ']': insertEOL = true tok = token.RBRACK case '{': tok = token.LBRACE case '}': insertEOL = true tok = token.RBRACE case '+': tok = token.ADD // Consider ++ for list concatenate. case '-': tok = token.SUB case '*': tok = token.MUL case '/': if s.ch == '/' { // comment if s.insertEOL { // reset position to the beginning of the comment s.ch = '/' s.offset = s.file.Offset(pos) s.rdOffset = s.offset + 1 s.insertEOL = false // newline consumed return s.file.Pos(offset, token.Elided), token.COMMA, "\n" } comment := s.scanComment() if s.mode&ScanComments == 0 { // skip comment s.insertEOL = false // newline consumed goto scanAgain } tok = token.COMMENT lit = comment } else { tok = token.QUO } // We no longer use %, but seems like a useful token to use for // something else at some point. // case '%': case '<': if s.ch == '-' { s.next() tok = token.ARROW } else { tok = s.switch2(token.LSS, token.LEQ) } case '>': tok = s.switch2(token.GTR, token.GEQ) case '=': if s.ch == '~' { s.next() tok = token.MAT } else { tok = s.switch2(token.BIND, token.EQL) } case '!': if s.ch == '~' { s.next() tok = token.NMAT } else { tok = s.switch2(token.NOT, token.NEQ) } case '&': switch s.ch { case '&': s.next() tok = token.LAND default: tok = token.AND } case '|': if s.ch == '|' { s.next() tok = token.LOR } else { tok = token.OR } default: // next reports unexpected BOMs - don't repeat if ch != bom { s.errf(s.file.Offset(pos), "illegal character %#U", ch) } insertEOL = s.insertEOL // preserve insertSemi info tok = token.ILLEGAL lit = string(ch) } } if s.mode&DontInsertCommas == 0 { s.insertEOL = insertEOL } s.linesSinceLast = 0 s.spacesSinceLast = 0 return } cue-lang-cue-db9cc73/cue/scanner/scanner_test.go000066400000000000000000000566671474664451600217500ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package scanner import ( "fmt" "os" "strings" "testing" "github.com/google/go-cmp/cmp" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" ) const /* class */ ( special = iota literal operator keyword ) func tokenclass(tok token.Token) int { switch { case tok.IsLiteral(): return literal case tok.IsOperator(): return operator case tok.IsKeyword(): return keyword } return special } type elt struct { tok token.Token lit string class int } var testTokens = [...]elt{ // Special tokens {token.COMMENT, "// a comment \n", special}, {token.COMMENT, "//\r\n", special}, // Attributes {token.ATTRIBUTE, "@foo()", special}, {token.ATTRIBUTE, "@foo(,,)", special}, {token.ATTRIBUTE, "@foo(a)", special}, {token.ATTRIBUTE, "@foo(aa=b)", special}, {token.ATTRIBUTE, "@foo(,a=b)", special}, {token.ATTRIBUTE, `@foo(",a=b")`, special}, {token.ATTRIBUTE, `@foo(##"\(),a=b"##)`, special}, {token.ATTRIBUTE, `@foo("",a="")`, special}, {token.ATTRIBUTE, `@foo(2,bytes,a.b=c)`, special}, {token.ATTRIBUTE, `@foo([{()}]())`, special}, {token.ATTRIBUTE, `@foo("{")`, special}, // Identifiers and basic type literals {token.BOTTOM, "_|_", literal}, {token.IDENT, "foobar", literal}, {token.IDENT, "$foobar", literal}, {token.IDENT, "#foobar", literal}, // {token.IDENT, "#0", literal}, {token.IDENT, "#", literal}, {token.IDENT, "_foobar", literal}, {token.IDENT, "__foobar", literal}, {token.IDENT, "#_foobar", literal}, {token.IDENT, "_#foobar", literal}, {token.IDENT, "__#foobar", literal}, {token.IDENT, "a۰۱۸", literal}, {token.IDENT, "foo६४", literal}, {token.IDENT, "bar9876", literal}, {token.IDENT, "ŝ", literal}, {token.IDENT, "ŝfoo", literal}, {token.INT, "0", literal}, {token.INT, "1", literal}, {token.INT, "123456789012345678890", literal}, {token.INT, "12345_67890_12345_6788_90", literal}, {token.INT, "1234567M", literal}, {token.INT, "1234567Mi", literal}, {token.INT, "1234567", literal}, {token.INT, ".3Mi", literal}, {token.INT, "3.3Mi", literal}, {token.INT, "0xcafebabe", literal}, {token.INT, "0b1100_1001", literal}, {token.INT, "0o1234567", literal}, {token.FLOAT, "0.", literal}, {token.FLOAT, ".0", literal}, {token.FLOAT, "3.14159265", literal}, {token.FLOAT, "1e0", literal}, {token.FLOAT, "1e+100", literal}, {token.FLOAT, "1e-100", literal}, {token.FLOAT, "1E+100", literal}, {token.FLOAT, "1E-100", literal}, {token.FLOAT, "0e-5", literal}, {token.FLOAT, "0e+100", literal}, {token.FLOAT, "0e-100", literal}, {token.FLOAT, "0E+100", literal}, {token.FLOAT, "0E-100", literal}, {token.FLOAT, "2.71828e-1000", literal}, {token.STRING, "'a'", literal}, {token.STRING, "'\\000'", literal}, {token.STRING, "'\\xFF'", literal}, {token.STRING, "'\\uff16'", literal}, {token.STRING, "'\\uD801'", literal}, {token.STRING, "'\\U0000ff16'", literal}, {token.STRING, "'foobar'", literal}, {token.STRING, `'foo\/bar'`, literal}, {token.STRING, `#" ""#`, literal}, {token.STRING, `#"" "#`, literal}, {token.STRING, `#""hello""#`, literal}, {token.STRING, `##""# "##`, literal}, {token.STRING, `####""###"####`, literal}, {token.STRING, "##\"\"\"\n\"\"\"#\n\"\"\"##", literal}, {token.STRING, `##"####"##`, literal}, {token.STRING, `#"foobar"#`, literal}, {token.STRING, `#" """#`, literal}, {token.STRING, `#"\r"#`, literal}, {token.STRING, `#"\("#`, literal}, {token.STRING, `#"\q"#`, literal}, {token.STRING, `###"\##q"###`, literal}, {token.STRING, "'" + `\r` + "'", literal}, {token.STRING, "'foo" + `\r\n` + "bar'", literal}, {token.STRING, `"foobar"`, literal}, {token.STRING, "\"\"\"\n foobar\n \"\"\"", literal}, {token.STRING, "#\"\"\"\n \\(foobar\n \"\"\"#", literal}, // TODO: should we preserve the \r instead and have it removed by the // literal parser? This would allow preserving \r for formatting without // changing the semantics of evaluation. {token.STRING, "#\"\"\"\r\n \\(foobar\n \"\"\"#", literal}, // Operators and delimiters {token.ADD, "+", operator}, {token.SUB, "-", operator}, {token.MUL, "*", operator}, {token.QUO, "/", operator}, {token.AND, "&", operator}, {token.OR, "|", operator}, {token.LAND, "&&", operator}, {token.LOR, "||", operator}, {token.EQL, "==", operator}, {token.LSS, "<", operator}, {token.GTR, ">", operator}, {token.BIND, "=", operator}, {token.NOT, "!", operator}, {token.NEQ, "!=", operator}, {token.LEQ, "<=", operator}, {token.GEQ, ">=", operator}, {token.ELLIPSIS, "...", operator}, {token.MAT, "=~", operator}, {token.NMAT, "!~", operator}, {token.LPAREN, "(", operator}, {token.LBRACK, "[", operator}, {token.LBRACE, "{", operator}, {token.COMMA, ",", operator}, {token.PERIOD, ".", operator}, {token.OPTION, "?", operator}, {token.RPAREN, ")", operator}, {token.RBRACK, "]", operator}, {token.RBRACE, "}", operator}, {token.COLON, ":", operator}, // Keywords {token.TRUE, "true", keyword}, {token.FALSE, "false", keyword}, {token.NULL, "null", keyword}, {token.FOR, "for", keyword}, {token.IF, "if", keyword}, {token.IN, "in", keyword}, } const whitespace = " \t \n\n\n" // to separate tokens var source = func() []byte { var src []byte for _, t := range testTokens { src = append(src, t.lit...) src = append(src, whitespace...) } return src }() func newlineCount(s string) int { n := 0 for i := 0; i < len(s); i++ { if s[i] == '\n' { n++ } } return n } func checkPosScan(t *testing.T, lit string, p token.Pos, expected token.Position) { pos := p.Position() if pos.Filename != expected.Filename { t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename) } if pos.Offset != expected.Offset { t.Errorf("bad position for %q: got %d, expected %d", lit, pos.Offset, expected.Offset) } if pos.Line != expected.Line { t.Errorf("bad line for %q: got %d, expected %d", lit, pos.Line, expected.Line) } if pos.Column != expected.Column { t.Errorf("bad column for %q: got %d, expected %d", lit, pos.Column, expected.Column) } } // Verify that calling Scan() provides the correct results. func TestScan(t *testing.T) { whitespace_linecount := newlineCount(whitespace) // error handler eh := func(_ token.Pos, msg string, args []interface{}) { t.Errorf("error handler called (msg = %s)", fmt.Sprintf(msg, args...)) } // verify scan var s Scanner s.Init(token.NewFile("", -1, len(source)), source, eh, ScanComments|DontInsertCommas) // set up expected position epos := token.Position{ Filename: "", Offset: 0, Line: 1, Column: 1, } index := 0 for { pos, tok, lit := s.Scan() // check position if tok == token.EOF { // correction for EOF epos.Line = newlineCount(string(source)) epos.Column = 2 } checkPosScan(t, lit, pos, epos) // check token e := elt{token.EOF, "", special} if index < len(testTokens) { e = testTokens[index] index++ } if tok != e.tok { t.Errorf("bad token for %q: got %s, expected %s", lit, tok, e.tok) } // check token class if tokenclass(tok) != e.class { t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class) } // check literal elit := "" switch e.tok { case token.COMMENT: // no CRs in comments elit = string(stripCR([]byte(e.lit))) //-style comment literal doesn't contain newline if elit[1] == '/' { elit = elit[0 : len(elit)-1] } case token.ATTRIBUTE: elit = e.lit case token.IDENT: elit = e.lit case token.COMMA: elit = "," default: if e.tok.IsLiteral() { // no CRs in raw string literals elit = e.lit if elit[0] == '`' { elit = string(stripCR([]byte(elit))) } } else if e.tok.IsKeyword() { elit = e.lit } } if lit != elit { t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit) } if tok == token.EOF { break } // update position epos.Offset += len(e.lit) + len(whitespace) epos.Line += newlineCount(e.lit) + whitespace_linecount } if s.ErrorCount != 0 { t.Errorf("found %d errors", s.ErrorCount) } } func checkComma(t *testing.T, line string, mode Mode) { var S Scanner file := token.NewFile("TestCommas", -1, len(line)) S.Init(file, []byte(line), nil, mode) pos, tok, lit := S.Scan() for tok != token.EOF { if tok == token.ILLEGAL { // the illegal token literal indicates what // kind of semicolon literal to expect commaLit := "\n" if lit[0] == '~' { commaLit = "," } // next token must be a comma commaPos := file.Position(pos) commaPos.Offset++ commaPos.Column++ pos, tok, lit = S.Scan() if tok == token.COMMA { if lit != commaLit { t.Errorf(`bad literal for %q: got %q (%q), expected %q`, line, lit, tok, commaLit) } checkPosScan(t, line, pos, commaPos) } else { t.Errorf("bad token for %q: got %s, expected ','", line, tok) } } else if tok == token.COMMA { t.Errorf("bad token for %q: got ',', expected no ','", line) } pos, tok, lit = S.Scan() } } var lines = []string{ // ~ indicates a comma present in the source // ^ indicates an automatically inserted comma "", "\ufeff~,", // first BOM is ignored "~,", "foo^\n", "_foo^\n", "123^\n", "1.2^\n", "'x'^\n", "_|_^\n", "_|_^\n", `"x"` + "^\n", "#'x'#^\n", `""" foo """` + "^\n", // `""" // foo \(bar) // """` + "^\n", `''' foo '''` + "^\n", "+\n", "-\n", "*\n", "/\n", "&\n", // "&^\n", "|\n", "&&\n", "||\n", "<-\n", "->\n", "==\n", "<\n", ">\n", "=\n", "!\n", "!=\n", "<=\n", ">=\n", ":=\n", "...^\n", "(\n", "[\n", "[[\n", "{\n", "{{\n", "~,\n", ".\n", ")^\n", "]^\n", "]]^\n", "}^\n", "}}^\n", ":\n", "::\n", ";^\n", "true^\n", "false^\n", "null^\n", "foo^//comment\n", "foo^//comment", "foo ^// comment\n", "foo ^// comment", "foo ^", "foo ^//", "package main^\n\nfoo: bar^", "package main^", } func TestCommas(t *testing.T) { for _, line := range lines { checkComma(t, line, 0) checkComma(t, line, ScanComments) // if the input ended in newlines, the input must tokenize the // same with or without those newlines for i := len(line) - 1; i >= 0 && line[i] == '\n'; i-- { checkComma(t, line[0:i], 0) checkComma(t, line[0:i], ScanComments) } } } func TestRelative(t *testing.T) { test := ` package foo // comment a: 1 // a b : 5 // line one // line two c : "dfs" , d: "foo" ` want := []string{ `newline IDENT package`, `blank IDENT foo`, "elided , \n", `section COMMENT // comment`, `newline IDENT a`, `nospace : `, `blank INT 1`, "elided , \n", `blank COMMENT // a`, `newline IDENT b`, `blank : `, `blank INT 5`, "elided , \n", "newline COMMENT // line one", "newline COMMENT // line two", `newline IDENT c`, `newline : `, `blank STRING "dfs"`, "newline , ,", "blank IDENT d", "nospace : ", `blank STRING "foo"`, "elided , \n", } var S Scanner f := token.NewFile("TestCommas", -1, len(test)) S.Init(f, []byte(test), nil, ScanComments) pos, tok, lit := S.Scan() got := []string{} for tok != token.EOF { got = append(got, fmt.Sprintf("%-7s %-8s %s", pos.RelPos(), tok, lit)) pos, tok, lit = S.Scan() } if diff := cmp.Diff(got, want); diff != "" { t.Error(diff) } } // Verify that initializing the same scanner more than once works correctly. func TestInit(t *testing.T) { var s Scanner // 1st init src1 := "false true { }" f1 := token.NewFile("src1", -1, len(src1)) s.Init(f1, []byte(src1), nil, DontInsertCommas) if f1.Size() != len(src1) { t.Errorf("bad file size: got %d, expected %d", f1.Size(), len(src1)) } s.Scan() // false s.Scan() // true _, tok, _ := s.Scan() // { if tok != token.LBRACE { t.Errorf("bad token: got %s, expected %s", tok, token.LBRACE) } // 2nd init src2 := "null true { ]" f2 := token.NewFile("src2", -1, len(src2)) s.Init(f2, []byte(src2), nil, DontInsertCommas) if f2.Size() != len(src2) { t.Errorf("bad file size: got %d, expected %d", f2.Size(), len(src2)) } _, tok, _ = s.Scan() // go if tok != token.NULL { t.Errorf("bad token: got %s, expected %s", tok, token.NULL) } if s.ErrorCount != 0 { t.Errorf("found %d errors", s.ErrorCount) } } func TestScanInterpolation(t *testing.T) { // error handler eh := func(pos token.Pos, msg string, args []interface{}) { msg = fmt.Sprintf(msg, args...) t.Errorf("error handler called (pos = %v, msg = %s)", pos, msg) } trim := func(s string) string { return strings.Trim(s, `#"\()`) } sources := []string{ `"first\(first)\\second\(second)"`, `#"first\#(first)\second\#(second)"#`, `"level\( ["foo", "level", level ][2] )end\( end )"`, `##"level\##( ["foo", "level", level ][2] )end\##( end )"##`, `"level\( { "foo": 1, "bar": level } )end\(end)"`, } for i, src := range sources { name := fmt.Sprintf("tsrc%d", i) t.Run(name, func(t *testing.T) { f := token.NewFile(name, -1, len(src)) // verify scan var s Scanner s.Init(f, []byte(src), eh, ScanComments) count := 0 var lit, str string for tok := token.ILLEGAL; tok != token.EOF; { switch tok { case token.LPAREN: count++ case token.RPAREN: if count--; count == 0 { str = trim(s.ResumeInterpolation()) } case token.INTERPOLATION: str = trim(lit) case token.IDENT: if lit != str { t.Errorf("str: got %v; want %v", lit, str) } } _, tok, lit = s.Scan() } }) } } func TestStdErrorHander(t *testing.T) { const src = "~\n" + // illegal character, cause an error "~ ~\n" + // two errors on the same line "//line File2:20\n" + "~\n" + // different file, but same line "//line File2:1\n" + "~ ~\n" + // same file, decreasing line number "//line File1:1\n" + "~ ~ ~" // original file, line 1 again var list errors.Error eh := func(pos token.Pos, msg string, args []interface{}) { list = errors.Append(list, errors.Newf(pos, msg, args...)) } var s Scanner s.Init(token.NewFile("File1", -1, len(src)), []byte(src), eh, DontInsertCommas) for { if _, tok, _ := s.Scan(); tok == token.EOF { break } } n := len(errors.Errors(list)) if n != s.ErrorCount { t.Errorf("found %d errors, expected %d", n, s.ErrorCount) } if n != 9 { t.Errorf("found %d raw errors, expected 9", n) errors.Print(os.Stderr, list, nil) } // Note that this is 9 errors when sanitized, and not 8, // as we currently don't support //line comment directives. n = len(errors.Errors(errors.Sanitize(list))) if n != 9 { t.Errorf("found %d one-per-line errors, expected 9", n) errors.Print(os.Stderr, list, nil) } } type errorCollector struct { cnt int // number of errors encountered msg string // last error message encountered pos token.Pos // last error position encountered } func checkError(t *testing.T, src string, tok token.Token, pos int, lit, err string) { t.Helper() var s Scanner var h errorCollector eh := func(pos token.Pos, msg string, args []interface{}) { h.cnt++ h.msg = fmt.Sprintf(msg, args...) h.pos = pos } s.Init(token.NewFile("", -1, len(src)), []byte(src), eh, ScanComments|DontInsertCommas) _, tok0, lit0 := s.Scan() if tok0 != tok { t.Errorf("%q: got %s, expected %s", src, tok0, tok) } if tok0 != token.ILLEGAL && lit0 != lit { t.Errorf("%q: got literal %q, expected %q", src, lit0, lit) } cnt := 0 if err != "" { cnt = 1 } if h.cnt != cnt { t.Errorf("%q: got cnt %d, expected %d", src, h.cnt, cnt) } if h.msg != err { t.Errorf("%q: got msg %q, expected %q", src, h.msg, err) } if h.pos.Offset() != pos { t.Errorf("%q: got offset %d, expected %d", src, h.pos.Offset(), pos) } } var errorTests = []struct { src string tok token.Token pos int lit string err string }{ {"`", token.ILLEGAL, 0, "", "illegal character U+0060 '`'"}, {"\a", token.ILLEGAL, 0, "", "illegal character U+0007"}, {`^`, token.ILLEGAL, 0, "", "illegal character U+005E '^'"}, {`…`, token.ILLEGAL, 0, "", "illegal character U+2026 '…'"}, {`_|`, token.ILLEGAL, 0, "", "illegal token '_|'; expected '_'"}, {`@`, token.ATTRIBUTE, 1, `@`, "invalid attribute: expected '('"}, {`@foo`, token.ATTRIBUTE, 4, `@foo`, "invalid attribute: expected '('"}, {`@foo(`, token.ATTRIBUTE, 5, `@foo(`, "attribute missing ')'"}, {`@foo( `, token.ATTRIBUTE, 6, `@foo( `, "attribute missing ')'"}, {`@foo( ""])`, token.ATTRIBUTE, 9, `@foo( ""])`, "unexpected ']'"}, {`@foo(3})`, token.ATTRIBUTE, 7, `@foo(3})`, "unexpected '}'"}, {`@foo(["")])`, token.ATTRIBUTE, 9, `@foo(["")])`, "unexpected ')'"}, {`@foo(""`, token.ATTRIBUTE, 7, `@foo(""`, "attribute missing ')'"}, {`@foo(aa`, token.ATTRIBUTE, 7, `@foo(aa`, "attribute missing ')'"}, {`@foo("\(())")`, token.ATTRIBUTE, 7, `@foo("\(())")`, "interpolation not allowed in attribute"}, // {`' '`, STRING, 0, `' '`, ""}, // {"`\0`", STRING, 3, `'\0'`, "illegal character U+0027 ''' in escape sequence"}, // {`'\07'`, STRING, 4, `'\07'`, "illegal character U+0027 ''' in escape sequence"}, {`"\8"`, token.STRING, 2, `"\8"`, "unknown escape sequence"}, {`"\08"`, token.STRING, 3, `"\08"`, "illegal character U+0038 '8' in escape sequence"}, {`"\x"`, token.STRING, 3, `"\x"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\x0"`, token.STRING, 4, `"\x0"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\x0g"`, token.STRING, 4, `"\x0g"`, "illegal character U+0067 'g' in escape sequence"}, {`"\u"`, token.STRING, 3, `"\u"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\u0"`, token.STRING, 4, `"\u0"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\u00"`, token.STRING, 5, `"\u00"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\u000"`, token.STRING, 6, `"\u000"`, "illegal character U+0022 '\"' in escape sequence"}, // {`"\u000`, token.STRING, 6, `"\u000`, "string literal not terminated"}, two errors {`"\u0000"`, token.STRING, 0, `"\u0000"`, ""}, {`"\U"`, token.STRING, 3, `"\U"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U0"`, token.STRING, 4, `"\U0"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U00"`, token.STRING, 5, `"\U00"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U000"`, token.STRING, 6, `"\U000"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U0000"`, token.STRING, 7, `"\U0000"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U00000"`, token.STRING, 8, `"\U00000"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U000000"`, token.STRING, 9, `"\U000000"`, "illegal character U+0022 '\"' in escape sequence"}, {`"\U0000000"`, token.STRING, 10, `"\U0000000"`, "illegal character U+0022 '\"' in escape sequence"}, // {`"\U0000000`, token.STRING, 10, `"\U0000000`, "string literal not terminated"}, // escape sequence not terminated"}, two errors {`"\U00000000"`, token.STRING, 0, `"\U00000000"`, ""}, {`"\Uffffffff"`, token.STRING, 2, `"\Uffffffff"`, "escape sequence is invalid Unicode code point"}, {`'`, token.STRING, 0, `'`, "string literal not terminated"}, {`"`, token.STRING, 0, `"`, "string literal not terminated"}, {`""`, token.STRING, 0, `""`, ""}, {`"abc`, token.STRING, 0, `"abc`, "string literal not terminated"}, {`""abc`, token.STRING, 0, `""`, ""}, {"\"\"\"\nabc", token.STRING, 0, "\"\"\"\nabc", "string literal not terminated"}, {"'''\nabc", token.STRING, 0, "'''\nabc", "string literal not terminated"}, {"\"abc\n", token.STRING, 0, `"abc`, "string literal not terminated"}, {"\"abc\n ", token.STRING, 0, `"abc`, "string literal not terminated"}, {"\"abc\r\n ", token.STRING, 0, "\"abc\r", "string literal not terminated"}, {`#""`, token.STRING, 0, `#""`, "string literal not terminated"}, {`#"""`, token.STRING, 0, `#"""`, `expected newline after multiline quote #"""`}, {`#""#`, token.STRING, 0, `#""#`, ""}, // {"$", IDENT, 0, "$", ""}, // TODO: for root of file? {"#'", token.STRING, 0, "#'", "string literal not terminated"}, {"''", token.STRING, 0, "''", ""}, {"'", token.STRING, 0, "'", "string literal not terminated"}, {`"\("`, token.INTERPOLATION, 0, `"\(`, ""}, {`#"\("#`, token.STRING, 0, `#"\("#`, ""}, {`#"\#("#`, token.INTERPOLATION, 0, `#"\#(`, ""}, {`"\q"`, token.STRING, 2, `"\q"`, "unknown escape sequence"}, {`#"\q"#`, token.STRING, 0, `#"\q"#`, ""}, {`#"\#q"#`, token.STRING, 4, `#"\#q"#`, "unknown escape sequence"}, {"0", token.INT, 0, "0", ""}, {"077", token.INT, 0, "077", "illegal integer number"}, {"078.", token.FLOAT, 0, "078.", ""}, {"07801234567.", token.FLOAT, 0, "07801234567.", ""}, {"078e0", token.FLOAT, 0, "078e0", ""}, {"078", token.INT, 0, "078", "illegal integer number"}, {"07800000009", token.INT, 0, "07800000009", "illegal integer number"}, {"0x", token.INT, 0, "0x", "illegal hexadecimal number"}, {"0X", token.INT, 0, "0X", "illegal hexadecimal number"}, {"0Xbeef_", token.INT, 6, "0Xbeef_", "illegal '_' in number"}, {"0Xbeef__beef", token.INT, 7, "0Xbeef__beef", "illegal '_' in number"}, {"0b", token.INT, 0, "0b", "illegal binary number"}, {"0o", token.INT, 0, "0o", "illegal octal number"}, // {"123456789012345678890_i", IMAG, 21, "123456789012345678890_i", "illegal '_' in number"}, {"\"abc\x00def\"", token.STRING, 4, "\"abc\x00def\"", "illegal character NUL"}, {"\"abc\x80def\"", token.STRING, 4, "\"abc\x80def\"", "illegal UTF-8 encoding"}, {"\ufeff\ufeff", token.ILLEGAL, 3, "\ufeff\ufeff", "illegal byte order mark"}, // only first BOM is ignored {"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"}, // only first BOM is ignored // {"`a\ufeff`", IDENT, 2, "`a\ufeff`", "illegal byte order mark"}, // only first BOM is ignored {`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored } func TestScanErrors(t *testing.T) { for _, e := range errorTests { t.Run(e.src, func(t *testing.T) { checkError(t, e.src, e.tok, e.pos, e.lit, e.err) }) } } // Verify that no comments show up as literal values when skipping comments. func TestNoLiteralComments(t *testing.T) { var src = ` a: { A: 1 // foo } #b: { B: 2 // foo } c: 3 // foo d: 4 // foo b anycode(): { // foo } ` var s Scanner s.Init(token.NewFile("", -1, len(src)), []byte(src), nil, 0) for { pos, tok, lit := s.Scan() class := tokenclass(tok) if lit != "" && class != keyword && class != literal && tok != token.COMMA { t.Errorf("%s: tok = %s, lit = %q", pos, tok, lit) } if tok <= token.EOF { break } } } func BenchmarkScan(b *testing.B) { b.StopTimer() file := token.NewFile("", -1, len(source)) var s Scanner b.StartTimer() for i := 0; i < b.N; i++ { s.Init(file, source, nil, ScanComments) for { _, tok, _ := s.Scan() if tok == token.EOF { break } } } } func BenchmarkScanFile(b *testing.B) { b.StopTimer() const filename = "go" src, err := os.ReadFile(filename) if err != nil { panic(err) } file := token.NewFile(filename, -1, len(src)) b.SetBytes(int64(len(src))) var s Scanner b.StartTimer() for i := 0; i < b.N; i++ { s.Init(file, src, nil, ScanComments) for { _, tok, _ := s.Scan() if tok == token.EOF { break } } } } cue-lang-cue-db9cc73/cue/stats/000077500000000000000000000000001474664451600164125ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/stats/stats.go000066400000000000000000000122661474664451600201060ustar00rootroot00000000000000// Copyright 2022 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package stats is an experimental package for getting statistics on CUE // evaluations. package stats import ( "strings" "sync" "text/template" "cuelang.org/go/internal" ) // Counts holds counters for key events during a CUE evaluation. // // This is an experimental type and the contents may change without notice. type Counts struct { // Note that we can't use the public [cuecontext.EvalVersion] type // as that would lead to an import cycle. We could use "int" but that's a bit odd. // There's no harm in referencing an internal type in practice, given that // the public type is a type alias for the internal type already. // EvalVersion is the evaluator version which was used for the CUE evaluation, // corresponding to one of the values under [cuelang.org/go/cue/cuecontext.EvalVersion]. EvalVersion internal.EvaluatorVersion // Operation counters // // These counters account for several key operations. // Unifications counts the number of calls to adt.Unify Unifications int64 // Disjuncts indicates the number of total disjuncts processed as part // of a Unify operation. A unification with no | operator counts as a // single disjunct, so Disjuncts is always greater than or equal to the // number of Unifications. // // If Disjuncts is much larger than Unification, this may indicate room // for optimization. In particular, most practical uses of disjunctions // should allow for near-linear processing. Disjuncts int64 // Conjuncts is an estimate of the number of conjunctions processed during // the calls to Unify. This includes the conjuncts added in the compilation // phase as well as the derivative conjuncts inserted from other nodes // after following references. // // A number of Conjuncts much larger than Disjuncts may indicate non-linear // algorithmic behavior. Conjuncts int64 // Buffer counters // // Each unification and disjunct operation is associated with an object // with temporary buffers. Reuse of this buffer is critical for performance. // The following counters track this. Freed int64 // Number of buffers returned to the free pool. Reused int64 // Number of times a buffer is reused instead of allocated. Allocs int64 // Total number of allocated buffer objects. Retained int64 // Number of times a buffer is retained upon finalization. } // TODO: None of the methods below protect against overflows or underflows. // If those start happening in practice, or if the counters get large enough, // add checks on each of the operations. func (c *Counts) Add(other Counts) { switch v, vo := c.EvalVersion, other.EvalVersion; { case v == internal.EvalVersionUnset: // The first time we add evaluator counts, we record the evaluator version being used. if vo == internal.EvalVersionUnset { panic("the first call to Counts.Add must provide an evaluator version") } c.EvalVersion = vo case v != vo: // Any further evaluator counts being added must match the same evaluator version. // // TODO(mvdan): this is currently not possible to enforce, as we collect stats globally // via [adt.AddStats] which includes stats from contexts created with different versions. // We likely need to refactor the collection of stats so that it is not global first. // panic(fmt.Sprintf("cannot mix evaluator versions in Counts.Add: %v vs %v", v, vo)) } c.Unifications += other.Unifications c.Conjuncts += other.Conjuncts c.Disjuncts += other.Disjuncts c.Freed += other.Freed c.Retained += other.Retained c.Reused += other.Reused c.Allocs += other.Allocs } func (c Counts) Since(start Counts) Counts { c.Unifications -= start.Unifications c.Conjuncts -= start.Conjuncts c.Disjuncts -= start.Disjuncts c.Freed -= start.Freed c.Retained -= start.Retained c.Reused -= start.Reused c.Allocs -= start.Allocs return c } // Leaks reports the number of nodeContext structs leaked. These are typically // benign, as they will just be garbage collected, as long as the pointer from // the original nodes has been eliminated or the original nodes are also not // referred to. But Leaks may have notable impact on performance, and thus // should be avoided. func (s Counts) Leaks() int64 { return s.Allocs + s.Reused - s.Freed } var stats = sync.OnceValue(func() *template.Template { return template.Must(template.New("stats").Parse(`{{"" -}} Leaks: {{.Leaks}} Freed: {{.Freed}} Reused: {{.Reused}} Allocs: {{.Allocs}} Retain: {{.Retained}} Unifications: {{.Unifications}} Conjuncts: {{.Conjuncts}} Disjuncts: {{.Disjuncts}}`)) }) func (s Counts) String() string { buf := &strings.Builder{} err := stats().Execute(buf, s) if err != nil { panic(err) } return buf.String() } cue-lang-cue-db9cc73/cue/syntax_test.go000066400000000000000000000117151474664451600201750ustar00rootroot00000000000000// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "strings" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/format" ) func TestSyntax(t *testing.T) { o := func(opts ...cue.Option) []cue.Option { return opts } _ = o testCases := []struct { name string in string path string options []cue.Option out string }{{ name: "preseve docs", in: ` // Aloha hello: "world" // Aloha2 if true { // Aloha3 if true { // Aloha4 hello2: "world" } } `, options: o(cue.Docs(true)), out: ` { // Aloha hello: "world" // Aloha2 if true { // Aloha3 if true { // Aloha4 hello2: "world" } } }`, }, { name: "partially resolvable", in: ` x: {} t: {name: string} output: [ ... {t & x.value}] `, options: o(cue.ResolveReferences(true)), out: ` { x: {} t: { name: string } output: [...t & x.value] }`, }, { name: "issue867", path: "output", in: ` x: {} t: {name: string} output: [ ... {t & x.value}] `, out: ` { [...T & {}.value] //cue:path: t let T = { name: string } }`}, { // Structural errors (and worse) are reported as is. name: "structural error", in: ` #List: { value: _ next: #List } a: b: #List `, path: "a", options: o(cue.ResolveReferences(true)), out: ` { b: _|_ // #List.next: structural cycle (and 1 more errors) }`, }, { name: "resolveReferences", path: "resource", in: ` // User 1 v1: #Deployment: { spec: { replicas: int containers: [...] other: option: int } incomplete: { // NOTE: the definition of "a" will be out of scope so this // reference will not be resolvable. // TODO: hoist the definition of "a" into a let expression. x: a.x y: 1 | 2 z: [1, 2][a.x] } // NOTE: structural cycles are eliminated from disjunctions. This // means the semantics of the type is not preserved. // TODO: should we change this? recursive: #List } a: {} #D: {} #List: { Value: _ Next: #List | *null } parameter: { image: string replicas: int } _mystring: string resource: v1.#Deployment & { spec: { replicas: parameter.replicas containers: [{ image: parameter.image name: "main" envs: [..._mystring] }] } } parameter: image: *"myimage" | string parameter: replicas: *2 | >=1 & <5 // User 2 parameter: replicas: int resource: spec: replicas: parameter.replicas parameter: replicas: 3 `, options: o(cue.ResolveReferences(true)), out: ` { spec: { replicas: 3 containers: [{ image: *"myimage" | string name: "main" envs: [...string] }] other: { option: int } } incomplete: { x: {}.x y: 1 | 2 z: [1, 2][{}.x] } recursive: { Value: _ Next: null } } `, }, { name: "issue2339", in: ` s: string if true { out: "\(s)": 3 } `, options: o(cue.ResolveReferences(true)), out: ` { s: string out: { "\(s)": 3 } } `, }, { name: "fragments", in: ` // #person is a real person #person: { children: [...#person] name: =~"^[A-Za-z0-9]+$" address: string } `, path: "#person.children", options: o(cue.Schema(), cue.Raw()), out: `[...#person]`, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { ctx := cuecontext.New() v := ctx.CompileString(tc.in) v = v.LookupPath(cue.ParsePath(tc.path)) syntax := v.Syntax(tc.options...) b, err := format.Node(syntax) if err != nil { t.Fatal(err) } got := strings.TrimSpace(string(b)) want := strings.TrimSpace(tc.out) if got != want { t.Errorf("got: %v; want %v", got, want) } }) } } func TestFragment(t *testing.T) { in := ` #person: { children: [...#person] }` ctx := cuecontext.New() v := ctx.CompileString(in) v = v.LookupPath(cue.ParsePath("#person.children")) syntax := v.Syntax(cue.Schema(), cue.Raw()).(ast.Expr) // Compile the fragment from within the scope it was derived. v = ctx.BuildExpr(syntax, cue.Scope(v)) // Generate the syntax, this time as self-contained. syntax = v.Syntax(cue.Schema()).(ast.Expr) b, err := format.Node(syntax) if err != nil { t.Fatal(err) } out := `{ [...PERSON.#x] //cue:path: #person let PERSON = { #x: { children: [...#person] } } }` got := strings.TrimSpace(string(b)) want := strings.TrimSpace(out) if got != want { t.Errorf("got: %v; want %v", got, want) } } cue-lang-cue-db9cc73/cue/testdata/000077500000000000000000000000001474664451600170655ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/basicrewrite/000077500000000000000000000000001474664451600215505ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/basicrewrite/000_errors.txtar000066400000000000000000000032541474664451600245330ustar00rootroot00000000000000#name: errors #evalPartial -- in.cue -- a: _|_ & _|_ b: null & _|_ c: b.a == _|_ d: _|_ != b.a e: _|_ == _|_ f: ({} & false) == _|_ g: _|_ != ({} & false) -- out/def -- a: _|_ // explicit error (_|_ literal) in source b: _|_ // explicit error (_|_ literal) in source c: true d: false e: true -- out/legacy-debug -- <0>{a: _|_(explicit error (_|_ literal) in source), b: _|_(explicit error (_|_ literal) in source), c: true, d: false, e: true} -- out/compile -- --- in.cue { a: (_|_(explicit error (_|_ literal) in source) & _|_(explicit error (_|_ literal) in source)) b: (null & _|_(explicit error (_|_ literal) in source)) c: (〈0;b〉.a == _|_(explicit error (_|_ literal) in source)) d: (_|_(explicit error (_|_ literal) in source) != 〈0;b〉.a) e: (_|_(explicit error (_|_ literal) in source) == _|_(explicit error (_|_ literal) in source)) f: (({} & false) == _|_(explicit error (_|_ literal) in source)) g: (_|_(explicit error (_|_ literal) in source) != ({} & false)) } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 7 Allocs: 3 Retain: 0 Unifications: 10 Conjuncts: 14 Disjuncts: 10 -- out/eval -- Errors: explicit error (_|_ literal) in source: ./in.cue:1:4 explicit error (_|_ literal) in source: ./in.cue:1:10 explicit error (_|_ literal) in source: ./in.cue:2:11 Result: (_|_){ // [user] a: (_|_){ // [user] explicit error (_|_ literal) in source: // ./in.cue:1:4 // explicit error (_|_ literal) in source: // ./in.cue:1:10 } b: (_|_){ // [user] explicit error (_|_ literal) in source: // ./in.cue:2:11 } c: (bool){ true } d: (bool){ false } e: (bool){ true } f: (bool){ true } g: (bool){ false } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/001_regexp.txtar000066400000000000000000000060701474664451600245110ustar00rootroot00000000000000#name: regexp #evalPartial -- in.cue -- c1: "a" =~ "a" c2: "foo" =~ "[a-z]{3}" c3: "foo" =~ "[a-z]{4}" c4: "foo" !~ "[a-z]{4}" b1: =~"a" b1: "a" b2: =~"[a-z]{3}" b2: "foo" b3: =~"[a-z]{4}" b3: "foo" b4: !~"[a-z]{4}" b4: "foo" s1: !="b" & =~"c" // =~"c" s2: =~"c" & !="b" // =~"c" s3: !="b" & =~"[a-z]" // != "b" & =~"[a-z]" s4: =~"[a-z]" & !="b" // != "b" & =~"[a-z]" e1: "foo" =~ 1 e2: "foo" !~ true e3: !="a" & <5 -- out/def -- c1: true c2: true c3: false c4: true b1: "a" b2: "foo" b3: _|_ // invalid value "foo" (does not match =~"[a-z]{4}") b4: "foo" s1: =~"c" s2: !="b" & =~"[a-z]" e1: _|_ // invalid operation "foo" =~ 1 (mismatched types string and int) e2: _|_ // invalid operation "foo" !~ true (mismatched types string and bool) e3: _|_ // conflicting values !="a" and <5 (mismatched types string and number) -- out/legacy-debug -- <0>{c1: true, c2: true, c3: false, c4: true, b1: "a", b2: "foo", b3: _|_((=~"[a-z]{4}" & "foo"):invalid value "foo" (does not match =~"[a-z]{4}")), b4: "foo", s1: =~"c", s2: (!="b" & =~"[a-z]"), e1: _|_(("foo" =~ 1):invalid operation "foo" =~ 1 (mismatched types string and int)), e2: _|_(("foo" !~ true):invalid operation "foo" !~ true (mismatched types string and bool)), e3: _|_((!="a" & <5):conflicting values !="a" and <5 (mismatched types string and number))} -- out/compile -- --- in.cue { c1: ("a" =~ "a") c2: ("foo" =~ "[a-z]{3}") c3: ("foo" =~ "[a-z]{4}") c4: ("foo" !~ "[a-z]{4}") b1: =~"a" b1: "a" b2: =~"[a-z]{3}" b2: "foo" b3: =~"[a-z]{4}" b3: "foo" b4: !~"[a-z]{4}" b4: "foo" s1: (!="b" & =~"c") s2: (=~"c" & !="b") s3: (!="b" & =~"[a-z]") s4: (=~"[a-z]" & !="b") e1: ("foo" =~ 1) e2: ("foo" !~ true) e3: (!="a" & <5) } -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 14 Allocs: 2 Retain: 0 Unifications: 16 Conjuncts: 25 Disjuncts: 16 -- out/eval -- Errors: e3: conflicting values !="a" and <5 (mismatched types string and number): ./in.cue:22:5 ./in.cue:22:13 b3: invalid value "foo" (out of bound =~"[a-z]{4}"): ./in.cue:10:5 ./in.cue:11:5 e1: cannot use 1 (type int) as type (string|bytes): ./in.cue:20:5 ./in.cue:20:14 e2: cannot use true (type bool) as type (string|bytes): ./in.cue:21:5 ./in.cue:21:14 Result: (_|_){ // [eval] c1: (bool){ true } c2: (bool){ true } c3: (bool){ false } c4: (bool){ true } b1: (string){ "a" } b2: (string){ "foo" } b3: (_|_){ // [eval] b3: invalid value "foo" (out of bound =~"[a-z]{4}"): // ./in.cue:10:5 // ./in.cue:11:5 } b4: (string){ "foo" } s1: (string){ =~"c" } s2: (string){ =~"c" } s3: (string){ &(!="b", =~"[a-z]") } s4: (string){ &(=~"[a-z]", !="b") } e1: (_|_){ // [eval] e1: cannot use 1 (type int) as type (string|bytes): // ./in.cue:20:5 // ./in.cue:20:14 } e2: (_|_){ // [eval] e2: cannot use true (type bool) as type (string|bytes): // ./in.cue:21:5 // ./in.cue:21:14 } e3: (_|_){ // [eval] e3: conflicting values !="a" and <5 (mismatched types string and number): // ./in.cue:22:5 // ./in.cue:22:13 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/002_arithmetic.txtar000066400000000000000000000125231474664451600253510ustar00rootroot00000000000000#name: arithmetic #evalPartial -- in.cue -- i1: 1 & int i2: 2 & int sum: -1 + +2 // 1 div1: 2.0 / 3 * 6 // 4 div2: 2 / 3 * 6 // 4 div3: 1.00 / 1.00 divZero: 1.0 / 0 div00: 0 / 0 b: 1 != 4 add: div1 + 1.0 idiv00: 0 div 0 imod00: 0 mod 0 iquo00: 0 quo 0 irem00: 0 rem 0 v1: 1.0T / 2.0 v2: 2.0 == 2 v3: 2.0 / 3.0 v5: i1 div i2 e0: 2 + "a" // these are now all alloweed // e1: 2.0 / i1 // e2: i1 / 2.0 // e3: 3.0 % i2 // e4: i1 % 2.0 e5: 1.0 div 2 e6: 2 rem 2.0 e7: 2 quo 2.0 e8: 1.0 mod 1 -- out/def -- i1: 1 i2: 2 sum: 1 div1: 4.00000000000000000000000 div2: 4.00000000000000000000000 div3: 1. divZero: _|_ // division by zero div00: _|_ // division undefined b: true add: 5.00000000000000000000000 idiv00: _|_ // division by zero imod00: _|_ // division by zero iquo00: _|_ // division by zero irem00: _|_ // division by zero v1: 5.0000000000e+11 v2: true v3: 0.666666666666666666666667 v5: 0 e0: _|_ // invalid operation 2 + "a" (mismatched types int and string) // these are now all alloweed // e1: 2.0 / i1 // e2: i1 / 2.0 // e3: 3.0 % i2 // e4: i1 % 2.0 e5: _|_ // invalid operation 1.0 div 2 (mismatched types float and int) e6: _|_ // invalid operation 2 rem 2.0 (mismatched types int and float) e7: _|_ // invalid operation 2 quo 2.0 (mismatched types int and float) e8: _|_ // invalid operation 1.0 mod 1 (mismatched types float and int) -- out/legacy-debug -- <0>{i1: 1, i2: 2, sum: 1, div1: 4.00000000000000000000000, div2: 4.00000000000000000000000, div3: 1., divZero: _|_((1.0 / 0):division by zero), div00: _|_((0 / 0):division undefined), b: true, add: 5.00000000000000000000000, idiv00: _|_((0 div 0):division by zero), imod00: _|_((0 mod 0):division by zero), iquo00: _|_((0 quo 0):division by zero), irem00: _|_((0 rem 0):division by zero), v1: 5.0000000000e+11, v2: true, v3: 0.666666666666666666666667, v5: 0, e0: _|_((2 + "a"):invalid operation 2 + "a" (mismatched types int and string)), e5: _|_((1.0 div 2):invalid operation 1.0 div 2 (mismatched types float and int)), e6: _|_((2 rem 2.0):invalid operation 2 rem 2.0 (mismatched types int and float)), e7: _|_((2 quo 2.0):invalid operation 2 quo 2.0 (mismatched types int and float)), e8: _|_((1.0 mod 1):invalid operation 1.0 mod 1 (mismatched types float and int))} -- out/compile -- --- in.cue { i1: (1 & int) i2: (2 & int) sum: (-1 + +2) div1: ((2.0 / 3) * 6) div2: ((2 / 3) * 6) div3: (1.00 / 1.00) divZero: (1.0 / 0) div00: (0 / 0) b: (1 != 4) add: (〈0;div1〉 + 1.0) idiv00: (0 div 0) imod00: (0 mod 0) iquo00: (0 quo 0) irem00: (0 rem 0) v1: (1000000000000 / 2.0) v2: (2.0 == 2) v3: (2.0 / 3.0) v5: (〈0;i1〉 div 〈0;i2〉) e0: (2 + "a") e5: (1.0 div 2) e6: (2 rem 2.0) e7: (2 quo 2.0) e8: (1.0 mod 1) } -- out/eval/stats -- Leaks: 0 Freed: 24 Reused: 22 Allocs: 2 Retain: 0 Unifications: 24 Conjuncts: 26 Disjuncts: 24 -- out/eval -- Errors: divZero: failed arithmetic: division by zero: ./in.cue:8:10 div00: failed arithmetic: division undefined: ./in.cue:9:10 idiv00: division by zero: ./in.cue:13:9 imod00: division by zero: ./in.cue:14:9 iquo00: division by zero: ./in.cue:15:9 irem00: division by zero: ./in.cue:16:9 e0: invalid operands 2 and "a" to '+' (type int and string): ./in.cue:23:5 ./in.cue:23:9 e5: invalid operands 1.0 and 2 to 'div' (type float and int): ./in.cue:29:5 ./in.cue:29:13 e6: invalid operands 2 and 2.0 to 'rem' (type int and float): ./in.cue:30:5 ./in.cue:30:11 e7: invalid operands 2 and 2.0 to 'quo' (type int and float): ./in.cue:31:5 ./in.cue:31:11 e8: invalid operands 1.0 and 1 to 'mod' (type float and int): ./in.cue:32:5 ./in.cue:32:13 Result: (_|_){ // [eval] i1: (int){ 1 } i2: (int){ 2 } sum: (int){ 1 } div1: (float){ 4.000000000000000000000000000000000 } div2: (float){ 4.000000000000000000000000000000000 } div3: (float){ 1.0 } divZero: (_|_){ // [eval] divZero: failed arithmetic: division by zero: // ./in.cue:8:10 } div00: (_|_){ // [eval] div00: failed arithmetic: division undefined: // ./in.cue:9:10 } b: (bool){ true } add: (float){ 5.000000000000000000000000000000000 } idiv00: (_|_){ // [eval] idiv00: division by zero: // ./in.cue:13:9 } imod00: (_|_){ // [eval] imod00: division by zero: // ./in.cue:14:9 } iquo00: (_|_){ // [eval] iquo00: division by zero: // ./in.cue:15:9 } irem00: (_|_){ // [eval] irem00: division by zero: // ./in.cue:16:9 } v1: (float){ 5.0E+11 } v2: (bool){ true } v3: (float){ 0.6666666666666666666666666666666667 } v5: (int){ 0 } e0: (_|_){ // [eval] e0: invalid operands 2 and "a" to '+' (type int and string): // ./in.cue:23:5 // ./in.cue:23:9 } e5: (_|_){ // [eval] e5: invalid operands 1.0 and 2 to 'div' (type float and int): // ./in.cue:29:5 // ./in.cue:29:13 } e6: (_|_){ // [eval] e6: invalid operands 2 and 2.0 to 'rem' (type int and float): // ./in.cue:30:5 // ./in.cue:30:11 } e7: (_|_){ // [eval] e7: invalid operands 2 and 2.0 to 'quo' (type int and float): // ./in.cue:31:5 // ./in.cue:31:11 } e8: (_|_){ // [eval] e8: invalid operands 1.0 and 1 to 'mod' (type float and int): // ./in.cue:32:5 // ./in.cue:32:13 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/003_integer-specific_arithmetic.txtar000066400000000000000000000114641474664451600306550ustar00rootroot00000000000000#name: integer-specific arithmetic #evalPartial -- in.cue -- q1: 5 quo 2 // 2 q2: 5 quo -2 // -2 q3: -5 quo 2 // -2 q4: -5 quo -2 // 2 qe1: 2.0 quo 1 qe2: 2 quo 1.0 r1: 5 rem 2 // 1 r2: 5 rem -2 // 1 r3: -5 rem 2 // -1 r4: -5 rem -2 // -1 re1: 2.0 rem 1 re2: 2 rem 1.0 d1: 5 div 2 // 2 d2: 5 div -2 // -2 d3: -5 div 2 // -3 d4: -5 div -2 // 3 de1: 2.0 div 1 de2: 2 div 1.0 m1: 5 mod 2 // 1 m2: 5 mod -2 // 1 m3: -5 mod 2 // 1 m4: -5 mod -2 // 1 me1: 2.0 mod 1 me2: 2 mod 1.0 -- out/def -- q1: 2 q2: -2 q3: -2 q4: 2 qe1: _|_ // invalid operation 2.0 quo 1 (mismatched types float and int) qe2: _|_ // invalid operation 2 quo 1.0 (mismatched types int and float) r1: 1 r2: 1 r3: -1 r4: -1 re1: _|_ // invalid operation 2.0 rem 1 (mismatched types float and int) re2: _|_ // invalid operation 2 rem 1.0 (mismatched types int and float) d1: 2 d2: -2 d3: -3 d4: 3 de1: _|_ // invalid operation 2.0 div 1 (mismatched types float and int) de2: _|_ // invalid operation 2 div 1.0 (mismatched types int and float) m1: 1 m2: 1 m3: 1 m4: 1 me1: _|_ // invalid operation 2.0 mod 1 (mismatched types float and int) me2: _|_ // invalid operation 2 mod 1.0 (mismatched types int and float) -- out/legacy-debug -- <0>{q1: 2, q2: -2, q3: -2, q4: 2, qe1: _|_((2.0 quo 1):invalid operation 2.0 quo 1 (mismatched types float and int)), qe2: _|_((2 quo 1.0):invalid operation 2 quo 1.0 (mismatched types int and float)), r1: 1, r2: 1, r3: -1, r4: -1, re1: _|_((2.0 rem 1):invalid operation 2.0 rem 1 (mismatched types float and int)), re2: _|_((2 rem 1.0):invalid operation 2 rem 1.0 (mismatched types int and float)), d1: 2, d2: -2, d3: -3, d4: 3, de1: _|_((2.0 div 1):invalid operation 2.0 div 1 (mismatched types float and int)), de2: _|_((2 div 1.0):invalid operation 2 div 1.0 (mismatched types int and float)), m1: 1, m2: 1, m3: 1, m4: 1, me1: _|_((2.0 mod 1):invalid operation 2.0 mod 1 (mismatched types float and int)), me2: _|_((2 mod 1.0):invalid operation 2 mod 1.0 (mismatched types int and float))} -- out/compile -- --- in.cue { q1: (5 quo 2) q2: (5 quo -2) q3: (-5 quo 2) q4: (-5 quo -2) qe1: (2.0 quo 1) qe2: (2 quo 1.0) r1: (5 rem 2) r2: (5 rem -2) r3: (-5 rem 2) r4: (-5 rem -2) re1: (2.0 rem 1) re2: (2 rem 1.0) d1: (5 div 2) d2: (5 div -2) d3: (-5 div 2) d4: (-5 div -2) de1: (2.0 div 1) de2: (2 div 1.0) m1: (5 mod 2) m2: (5 mod -2) m3: (-5 mod 2) m4: (-5 mod -2) me1: (2.0 mod 1) me2: (2 mod 1.0) } -- out/eval/stats -- Leaks: 0 Freed: 25 Reused: 23 Allocs: 2 Retain: 0 Unifications: 25 Conjuncts: 25 Disjuncts: 25 -- out/eval -- Errors: qe1: invalid operands 2.0 and 1 to 'quo' (type float and int): ./in.cue:5:6 ./in.cue:5:14 qe2: invalid operands 2 and 1.0 to 'quo' (type int and float): ./in.cue:6:6 ./in.cue:6:12 re1: invalid operands 2.0 and 1 to 'rem' (type float and int): ./in.cue:12:6 ./in.cue:12:14 re2: invalid operands 2 and 1.0 to 'rem' (type int and float): ./in.cue:13:6 ./in.cue:13:12 de1: invalid operands 2.0 and 1 to 'div' (type float and int): ./in.cue:19:6 ./in.cue:19:14 de2: invalid operands 2 and 1.0 to 'div' (type int and float): ./in.cue:20:6 ./in.cue:20:12 me1: invalid operands 2.0 and 1 to 'mod' (type float and int): ./in.cue:26:6 ./in.cue:26:14 me2: invalid operands 2 and 1.0 to 'mod' (type int and float): ./in.cue:27:6 ./in.cue:27:12 Result: (_|_){ // [eval] q1: (int){ 2 } q2: (int){ -2 } q3: (int){ -2 } q4: (int){ 2 } qe1: (_|_){ // [eval] qe1: invalid operands 2.0 and 1 to 'quo' (type float and int): // ./in.cue:5:6 // ./in.cue:5:14 } qe2: (_|_){ // [eval] qe2: invalid operands 2 and 1.0 to 'quo' (type int and float): // ./in.cue:6:6 // ./in.cue:6:12 } r1: (int){ 1 } r2: (int){ 1 } r3: (int){ -1 } r4: (int){ -1 } re1: (_|_){ // [eval] re1: invalid operands 2.0 and 1 to 'rem' (type float and int): // ./in.cue:12:6 // ./in.cue:12:14 } re2: (_|_){ // [eval] re2: invalid operands 2 and 1.0 to 'rem' (type int and float): // ./in.cue:13:6 // ./in.cue:13:12 } d1: (int){ 2 } d2: (int){ -2 } d3: (int){ -3 } d4: (int){ 3 } de1: (_|_){ // [eval] de1: invalid operands 2.0 and 1 to 'div' (type float and int): // ./in.cue:19:6 // ./in.cue:19:14 } de2: (_|_){ // [eval] de2: invalid operands 2 and 1.0 to 'div' (type int and float): // ./in.cue:20:6 // ./in.cue:20:12 } m1: (int){ 1 } m2: (int){ 1 } m3: (int){ 1 } m4: (int){ 1 } me1: (_|_){ // [eval] me1: invalid operands 2.0 and 1 to 'mod' (type float and int): // ./in.cue:26:6 // ./in.cue:26:14 } me2: (_|_){ // [eval] me2: invalid operands 2 and 1.0 to 'mod' (type int and float): // ./in.cue:27:6 // ./in.cue:27:12 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/004_booleans.txtar000066400000000000000000000013761474664451600250300ustar00rootroot00000000000000#name: booleans #evalPartial -- in.cue -- t: true t: !false f: false f: !t e: true e: !true -- out/def -- t: true f: false e: _|_ // conflicting values true and false -- out/legacy-debug -- <0>{t: true, f: false, e: _|_(true:conflicting values true and false)} -- out/compile -- --- in.cue { t: true t: !false f: false f: !〈0;t〉 e: true e: !true } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 2 Allocs: 2 Retain: 0 Unifications: 4 Conjuncts: 7 Disjuncts: 4 -- out/eval -- Errors: e: conflicting values false and true: ./in.cue:5:4 ./in.cue:6:4 Result: (_|_){ // [eval] t: (bool){ true } f: (bool){ false } e: (_|_){ // [eval] e: conflicting values false and true: // ./in.cue:5:4 // ./in.cue:6:4 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/005_boolean_arithmetic.txtar000066400000000000000000000017351474664451600270560ustar00rootroot00000000000000#name: boolean arithmetic #evalPartial -- in.cue -- a: true && true b: true || false c: false == true d: false != true e: true & true f: true & false -- out/def -- a: true b: true c: false d: true e: true f: _|_ // conflicting values true and false -- out/legacy-debug -- <0>{a: true, b: true, c: false, d: true, e: true, f: _|_(true:conflicting values true and false)} -- out/compile -- --- in.cue { a: (true && true) b: (true || false) c: (false == true) d: (false != true) e: (true & true) f: (true & false) } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 5 Allocs: 2 Retain: 0 Unifications: 7 Conjuncts: 9 Disjuncts: 7 -- out/eval -- Errors: f: conflicting values false and true: ./in.cue:6:4 ./in.cue:6:11 Result: (_|_){ // [eval] a: (bool){ true } b: (bool){ true } c: (bool){ false } d: (bool){ true } e: (bool){ true } f: (_|_){ // [eval] f: conflicting values false and true: // ./in.cue:6:4 // ./in.cue:6:11 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/006_basic_type.txtar000066400000000000000000000020701474664451600253420ustar00rootroot00000000000000#name: basic type #evalPartial -- in.cue -- a: 1 & int b: number & 1 c: 1.0 c: float d: int & float // _|_ e: "4" & string f: true f: bool -- out/def -- a: 1 b: 1 c: 1.0 d: _|_ // conflicting values int and float (mismatched types int and float) e: "4" f: true -- out/legacy-debug -- <0>{a: 1, b: 1, c: 1.0, d: _|_((int & float):conflicting values int and float (mismatched types int and float)), e: "4", f: true} -- out/compile -- --- in.cue { a: (1 & int) b: (number & 1) c: 1.0 c: float d: (int & float) e: ("4" & string) f: true f: bool } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 5 Allocs: 2 Retain: 0 Unifications: 7 Conjuncts: 13 Disjuncts: 7 -- out/eval -- Errors: d: conflicting values int and float (mismatched types int and float): ./in.cue:5:4 ./in.cue:5:10 Result: (_|_){ // [eval] a: (int){ 1 } b: (int){ 1 } c: (float){ 1.0 } d: (_|_){ // [eval] d: conflicting values int and float (mismatched types int and float): // ./in.cue:5:4 // ./in.cue:5:10 } e: (string){ "4" } f: (bool){ true } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/007_strings_and_bytes.txtar000066400000000000000000000034751474664451600267540ustar00rootroot00000000000000#name: strings and bytes #evalPartial -- in.cue -- s0: "foo" + "bar" s1: 3 * "abc" s2: "abc" * 2 b0: 'foo' + 'bar' b1: 3 * 'abc' b2: 'abc' * 2 // TODO: consider the semantics of this and perhaps allow this. e0: "a" + '' e1: 'b' + "c" -- out/def -- s0: "foobar" s1: "abcabcabc" s2: "abcabc" b0: 'foobar' b1: 'abcabcabc' b2: 'abcabc' // TODO: consider the semantics of this and perhaps allow this. e0: _|_ // invalid operation "a" + '' (mismatched types string and bytes) e1: _|_ // invalid operation 'b' + "c" (mismatched types bytes and string) -- out/legacy-debug -- <0>{s0: "foobar", s1: "abcabcabc", s2: "abcabc", b0: 'foobar', b1: 'abcabcabc', b2: 'abcabc', e0: _|_(("a" + ''):invalid operation "a" + '' (mismatched types string and bytes)), e1: _|_(('b' + "c"):invalid operation 'b' + "c" (mismatched types bytes and string))} -- out/compile -- --- in.cue { s0: ("foo" + "bar") s1: (3 * "abc") s2: ("abc" * 2) b0: ('foo' + 'bar') b1: (3 * 'abc') b2: ('abc' * 2) e0: ("a" + '') e1: ('b' + "c") } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 7 Allocs: 2 Retain: 0 Unifications: 9 Conjuncts: 9 Disjuncts: 9 -- out/eval -- Errors: e0: invalid operands "a" and '' to '+' (type string and bytes): ./in.cue:10:5 ./in.cue:10:11 e1: invalid operands 'b' and "c" to '+' (type bytes and string): ./in.cue:11:5 ./in.cue:11:11 Result: (_|_){ // [eval] s0: (string){ "foobar" } s1: (string){ "abcabcabc" } s2: (string){ "abcabc" } b0: (bytes){ 'foobar' } b1: (bytes){ 'abcabcabc' } b2: (bytes){ 'abcabc' } e0: (_|_){ // [eval] e0: invalid operands "a" and '' to '+' (type string and bytes): // ./in.cue:10:5 // ./in.cue:10:11 } e1: (_|_){ // [eval] e1: invalid operands 'b' and "c" to '+' (type bytes and string): // ./in.cue:11:5 // ./in.cue:11:11 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/008_escaping.txtar000066400000000000000000000014261474664451600250170ustar00rootroot00000000000000#name: escaping #evalPartial -- in.cue -- a: "foo\nbar" b: a // TODO: mimic http://exploringjs.com/es6/ch_template-literals.html#sec_introduction-template-literals -- out/def -- a: """ foo bar """ b: """ foo bar """ -- out/export -- a: """ foo bar """ b: """ foo bar """ -- out/yaml -- a: |- foo bar b: |- foo bar -- out/json -- {"a":"foo\nbar","b":"foo\nbar"} -- out/legacy-debug -- <0>{a: "foo\nbar", b: "foo\nbar"} -- out/compile -- --- in.cue { a: "foo\nbar" b: 〈0;a〉 } -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 1 Allocs: 2 Retain: 0 Unifications: 3 Conjuncts: 4 Disjuncts: 3 -- out/eval -- (struct){ a: (string){ "foo\nbar" } b: (string){ "foo\nbar" } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/009_reference.txtar000066400000000000000000000020111474664451600251540ustar00rootroot00000000000000#name: reference #evalPartial -- in.cue -- a: b b: 2 d: { d: 3 e: d } e: { e: { v: 1 } f: { v: e.v } } -- out/def -- a: 2 b: 2 d: { d: 3 e: 3 } e: { e: { v: 1 } f: { v: 1 } } -- out/export -- a: 2 b: 2 d: { d: 3 e: 3 } e: { e: { v: 1 } f: { v: 1 } } -- out/yaml -- a: 2 b: 2 d: d: 3 e: 3 e: e: v: 1 f: v: 1 -- out/json -- {"a":2,"b":2,"d":{"d":3,"e":3},"e":{"e":{"v":1},"f":{"v":1}}} -- out/legacy-debug -- <0>{a: 2, b: 2, d: <1>{d: 3, e: 3}, e: <2>{e: <3>{v: 1}, f: <4>{v: 1}}} -- out/compile -- --- in.cue { a: 〈0;b〉 b: 2 d: { d: 3 e: 〈0;d〉 } e: { e: { v: 1 } f: { v: 〈1;e〉.v } } } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 7 Allocs: 4 Retain: 1 Unifications: 11 Conjuncts: 13 Disjuncts: 11 -- out/eval -- (struct){ a: (int){ 2 } b: (int){ 2 } d: (struct){ d: (int){ 3 } e: (int){ 3 } } e: (struct){ e: (struct){ v: (int){ 1 } } f: (struct){ v: (int){ 1 } } } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/010_lists.txtar000066400000000000000000000121421474664451600243520ustar00rootroot00000000000000#name: lists #evalPartial -- in.cue -- list: [1, 2, 3] index: [1, 2, 3][1] unify: [1, 2, 3] & [_, 2, 3] e: [] & 4 e2: [3]["d"] e3: [3][-1] e4: [1, 2, ...>=4 & <=5] & [1, 2, 4, 8] e5: [1, 2, 4, 8] & [1, 2, ...>=4 & <=5] -- out/def -- list: [1, 2, 3] index: 2 unify: [1, 2, 3] e: _|_ // conflicting values [] and 4 (mismatched types list and int) e2: _|_ // invalid list index "d" (type string) e3: _|_ // invalid list index -1 (index must be non-negative) e4: [1, 2, 4, _|_, // invalid value 8 (out of bound <=5) ] e5: [1, 2, 4, _|_, // invalid value 8 (out of bound <=5) ] -- out/legacy-debug -- <0>{list: [1,2,3], index: 2, unify: [1,2,3], e: _|_(([] & 4):conflicting values [] and 4 (mismatched types list and int)), e2: _|_("d":invalid list index "d" (type string)), e3: _|_(-1:invalid list index -1 (index must be non-negative)), e4: [1,2,4,_|_((<=5 & 8):invalid value 8 (out of bound <=5))], e5: [1,2,4,_|_((<=5 & 8):invalid value 8 (out of bound <=5))]} -- out/compile -- --- in.cue { list: [ 1, 2, 3, ] index: [ 1, 2, 3, ][1] unify: ([ 1, 2, 3, ] & [ _, 2, 3, ]) e: ([] & 4) e2: [ 3, ]["d"] e3: [ 3, ][-1] e4: ([ 1, 2, ...(>=4 & <=5), ] & [ 1, 2, 4, 8, ]) e5: ([ 1, 2, 4, 8, ] & [ 1, 2, ...(>=4 & <=5), ]) } -- out/eval/stats -- Leaks: 4 Freed: 23 Reused: 20 Allocs: 7 Retain: 4 Unifications: 27 Conjuncts: 46 Disjuncts: 26 -- out/evalalpha -- Errors: e: conflicting values [] and 4 (mismatched types list and int): ./in.cue:4:8 ./in.cue:4:13 e2: undefined field: d: ./in.cue:5:12 e3: invalid index -1 (index must be non-negative): ./in.cue:6:8 ./in.cue:6:12 e4.3: invalid value 8 (out of bound <=5): ./in.cue:7:24 ./in.cue:7:41 e5.3: invalid value 8 (out of bound <=5): ./in.cue:8:39 ./in.cue:8:18 Result: (_|_){ // [eval] list: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } index: (int){ 2 } unify: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } e: (_|_){ // [eval] e: conflicting values [] and 4 (mismatched types list and int): // ./in.cue:4:8 // ./in.cue:4:13 } e2: (_|_){ // [eval] e2: undefined field: d: // ./in.cue:5:12 } e3: (_|_){ // [eval] e3: invalid index -1 (index must be non-negative): // ./in.cue:6:8 // ./in.cue:6:12 } e4: (_|_){ // [eval] 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 4 } 3: (_|_){ // [eval] e4.3: invalid value 8 (out of bound <=5): // ./in.cue:7:24 // ./in.cue:7:41 } } e5: (_|_){ // [eval] 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 4 } 3: (_|_){ // [eval] e5.3: invalid value 8 (out of bound <=5): // ./in.cue:8:39 // ./in.cue:8:18 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,8 +1,8 @@ Errors: -e: conflicting values 4 and [] (mismatched types int and list): +e: conflicting values [] and 4 (mismatched types list and int): ./in.cue:4:8 ./in.cue:4:13 -e2: invalid list index d (type string): +e2: undefined field: d: ./in.cue:5:12 e3: invalid index -1 (index must be non-negative): ./in.cue:6:8 @@ -29,12 +29,12 @@ 2: (int){ 3 } } e: (_|_){ - // [eval] e: conflicting values 4 and [] (mismatched types int and list): + // [eval] e: conflicting values [] and 4 (mismatched types list and int): // ./in.cue:4:8 // ./in.cue:4:13 } e2: (_|_){ - // [eval] e2: invalid list index d (type string): + // [eval] e2: undefined field: d: // ./in.cue:5:12 } e3: (_|_){ -- diff/todo/p2 -- error: more precise message -- out/eval -- Errors: e: conflicting values 4 and [] (mismatched types int and list): ./in.cue:4:8 ./in.cue:4:13 e2: invalid list index d (type string): ./in.cue:5:12 e3: invalid index -1 (index must be non-negative): ./in.cue:6:8 ./in.cue:6:12 e4.3: invalid value 8 (out of bound <=5): ./in.cue:7:24 ./in.cue:7:41 e5.3: invalid value 8 (out of bound <=5): ./in.cue:8:39 ./in.cue:8:18 Result: (_|_){ // [eval] list: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } index: (int){ 2 } unify: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } e: (_|_){ // [eval] e: conflicting values 4 and [] (mismatched types int and list): // ./in.cue:4:8 // ./in.cue:4:13 } e2: (_|_){ // [eval] e2: invalid list index d (type string): // ./in.cue:5:12 } e3: (_|_){ // [eval] e3: invalid index -1 (index must be non-negative): // ./in.cue:6:8 // ./in.cue:6:12 } e4: (_|_){ // [eval] 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 4 } 3: (_|_){ // [eval] e4.3: invalid value 8 (out of bound <=5): // ./in.cue:7:24 // ./in.cue:7:41 } } e5: (_|_){ // [eval] 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 4 } 3: (_|_){ // [eval] e5.3: invalid value 8 (out of bound <=5): // ./in.cue:8:39 // ./in.cue:8:18 } } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/012_selecting.txtar000066400000000000000000000060231474664451600251740ustar00rootroot00000000000000#name: selecting #evalPartial -- in.cue -- obj: {a: 1, b: 2} index: {a: 1, b: 2}["b"] mulidx: {a: 1, b: {a: 1, b: 3}}["b"]["b"] e: {a: 1}[4] f: {a: 1}.b g: {a: 1}["b"] h: [3].b -- out/def -- obj: { a: 1 b: 2 } index: 2 mulidx: 3 e: _|_ // invalid struct index 4 (type int) f: { a: 1 }.b g: { a: 1 }["b"] h: _|_ // invalid operation: [3].b (type list does not support selection) -- out/legacy-debug -- <0>{obj: <1>{a: 1, b: 2}, index: 2, mulidx: 3, e: _|_(4:invalid struct index 4 (type int)), f: <2>{a: 1}.b, g: <3>{a: 1}["b"], h: _|_([3]:invalid operation: [3].b (type list does not support selection))} -- out/compile -- --- in.cue { obj: { a: 1 b: 2 } index: { a: 1 b: 2 }["b"] mulidx: { a: 1 b: { a: 1 b: 3 } }["b"]["b"] e: { a: 1 }[4] f: { a: 1 }.b g: { a: 1 }["b"] h: [ 3, ].b } -- out/eval/stats -- Leaks: 9 Freed: 10 Reused: 8 Allocs: 11 Retain: 9 Unifications: 19 Conjuncts: 19 Disjuncts: 17 -- out/eval -- Errors: e: invalid struct selector 4 (type int): ./in.cue:4:16 h: invalid list index b (type string): ./in.cue:7:13 Result: (_|_){ // [eval] obj: (struct){ a: (int){ 1 } b: (int){ 2 } } index: (int){ 2 } mulidx: (int){ 3 } e: (_|_){ // [eval] e: invalid struct selector 4 (type int): // ./in.cue:4:16 } f: (_|_){ // [incomplete] f: undefined field: b: // ./in.cue:5:16 } g: (_|_){ // [incomplete] g: undefined field: b: // ./in.cue:6:16 } h: (_|_){ // [eval] h: invalid list index b (type string): // ./in.cue:7:13 } } -- out/evalalpha -- Errors: e: index out of range [4] with length 0: ./in.cue:4:16 h: undefined field: b: ./in.cue:7:13 Result: (_|_){ // [eval] obj: (struct){ a: (int){ 1 } b: (int){ 2 } } index: (int){ 2 } mulidx: (int){ 3 } e: (_|_){ // [eval] e: index out of range [4] with length 0: // ./in.cue:4:16 } f: (_|_){ // [incomplete] f: undefined field: b: // ./in.cue:5:16 } g: (_|_){ // [incomplete] g: undefined field: b: // ./in.cue:6:16 } h: (_|_){ // [eval] h: undefined field: b: // ./in.cue:7:13 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,7 @@ Errors: -e: invalid struct selector 4 (type int): +e: index out of range [4] with length 0: ./in.cue:4:16 -h: invalid list index b (type string): +h: undefined field: b: ./in.cue:7:13 Result: @@ -14,7 +14,7 @@ index: (int){ 2 } mulidx: (int){ 3 } e: (_|_){ - // [eval] e: invalid struct selector 4 (type int): + // [eval] e: index out of range [4] with length 0: // ./in.cue:4:16 } f: (_|_){ @@ -26,7 +26,7 @@ // ./in.cue:6:16 } h: (_|_){ - // [eval] h: invalid list index b (type string): + // [eval] h: undefined field: b: // ./in.cue:7:13 } } -- diff/explanation -- Better error message for undefined field in new. Other error got worse, but this is covered elsewhere. cue-lang-cue-db9cc73/cue/testdata/basicrewrite/013_obj_unify.txtar000066400000000000000000000057541474664451600252160ustar00rootroot00000000000000#name: obj unify #evalPartial -- in.cue -- o1: {a: 1} & {b: 2} // {a:1,b:2} o2: {a: 1, b: 2} & {b: 2} // {a:1,b:2} o3: {a: 1} & {a: 1, b: 2} // {a:1,b:2} o4: {a: 1} & {b: 2} // {a:1,b:2} o4: {a: 1, b: 2} & {b: 2} o4: {a: 1} & {a: 1, b: 2} e: 1 // 1 & {a:3} e: {a: 3} -- out/def -- o1: { a: 1 b: 2 } o2: { a: 1 b: 2 } o3: { a: 1 b: 2 } o4: { a: 1 b: 2 } e: _|_ // conflicting values 1 and {a: 3} (mismatched types int and struct) -- out/legacy-debug -- <0>{o1: <1>{a: 1, b: 2}, o2: <2>{a: 1, b: 2}, o3: <3>{a: 1, b: 2}, o4: <4>{a: 1, b: 2}, e: _|_((1 & <5>{a: 3}):conflicting values 1 and {a: 3} (mismatched types int and struct))} -- out/compile -- --- in.cue { o1: ({ a: 1 } & { b: 2 }) o2: ({ a: 1 b: 2 } & { b: 2 }) o3: ({ a: 1 } & { a: 1 b: 2 }) o4: ({ a: 1 } & { b: 2 }) o4: ({ a: 1 b: 2 } & { b: 2 }) o4: ({ a: 1 } & { a: 1 b: 2 }) e: 1 e: { a: 3 } } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 12 Allocs: 3 Retain: 0 Unifications: 15 Conjuncts: 32 Disjuncts: 15 -- out/evalalpha -- Errors: e: conflicting values 1 and {a:3} (mismatched types int and struct): ./in.cue:7:5 ./in.cue:8:4 e: cannot combine regular field "a" with 1: ./in.cue:8:8 ./in.cue:7:5 Result: (_|_){ // [eval] o1: (struct){ a: (int){ 1 } b: (int){ 2 } } o2: (struct){ a: (int){ 1 } b: (int){ 2 } } o3: (struct){ a: (int){ 1 } b: (int){ 2 } } o4: (struct){ a: (int){ 1 } b: (int){ 2 } } e: (_|_){ // [eval] e: conflicting values 1 and {a:3} (mismatched types int and struct): // ./in.cue:7:5 // ./in.cue:8:4 // e: cannot combine regular field "a" with 1: // ./in.cue:8:8 // ./in.cue:7:5 a: (int){ 3 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,6 +2,9 @@ e: conflicting values 1 and {a:3} (mismatched types int and struct): ./in.cue:7:5 ./in.cue:8:4 +e: cannot combine regular field "a" with 1: + ./in.cue:8:8 + ./in.cue:7:5 Result: (_|_){ @@ -26,6 +29,9 @@ // [eval] e: conflicting values 1 and {a:3} (mismatched types int and struct): // ./in.cue:7:5 // ./in.cue:8:4 + // e: cannot combine regular field "a" with 1: + // ./in.cue:8:8 + // ./in.cue:7:5 a: (int){ 3 } } } -- diff/explanation -- An extra error messages that is correct, but not required. -- out/eval -- Errors: e: conflicting values 1 and {a:3} (mismatched types int and struct): ./in.cue:7:5 ./in.cue:8:4 Result: (_|_){ // [eval] o1: (struct){ a: (int){ 1 } b: (int){ 2 } } o2: (struct){ a: (int){ 1 } b: (int){ 2 } } o3: (struct){ a: (int){ 1 } b: (int){ 2 } } o4: (struct){ a: (int){ 1 } b: (int){ 2 } } e: (_|_){ // [eval] e: conflicting values 1 and {a:3} (mismatched types int and struct): // ./in.cue:7:5 // ./in.cue:8:4 a: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/014_disjunctions.txtar000066400000000000000000000050601474664451600257350ustar00rootroot00000000000000#name: disjunctions #evalPartial -- in.cue -- o1: 1 | 2 | 3 o2: (1 | 2 | 3) & 1 o3: 2 & (1 | *2 | 3) o4: (1 | *2 | 3) & (1 | 2 | *3) o5: (1 | *2 | 3) & (3 | *2 | 1) o6: (1 | 2 | 3) & (3 | 1 | 2) o7: (1 | 2 | 3) & (2 | 3) o8: (1 | 2 | 3) & (3 | 2) o9: (2 | 3) & (1 | 2 | 3) o10: (3 | 2) & (1 | *2 | 3) m1: (1 | (*2 | 3)) & (>=2 & <=3) m2: (1 | (*2 | 3)) & (2 | 3) m3: (*1 | *(*2 | 3)) & (2 | 3) m4: (2 | 3) & (*2 | 3) m5: (*2 | 3) & (2 | 3) // (*2 | 3) & (2 | 3) // (2 | 3) & (*2 | 3) // 2&(*2 | 3) | 3&(*2 | 3) // (*1 | (*2 | 3)) & (2 | 3) // *1& (2 | 3) | (*2 | 3)&(2 | 3) // *2&(2 | 3) | 3&(2 | 3) // (2 | 3)&(*1 | (*2 | 3)) // 2&(*1 | (*2 | 3)) | 3&(*1 | (*2 | 3)) // *1&2 | (*2 | 3)&2 | *1&3 | (*2 | 3)&3 // (*2 | 3)&2 | (*2 | 3)&3 // *2 | 3 // All errors are treated the same as per the unification model. i1: [1, 2][3] | "c" -- out/def -- o1: 1 | 2 | 3 o2: 1 o3: 2 o4: 1 | 2 | 3 | *_|_ o5: 1 | *2 | 3 o6: 1 | 2 | 3 o7: 2 | 3 o8: 2 | 3 o9: 2 | 3 o10: 3 | *2 m1: *2 | 3 m2: *2 | 3 m3: *2 | 3 m4: *2 | 3 m5: *2 | 3 // All errors are treated the same as per the unification model. i1: "c" -- out/legacy-debug -- <0>{o1: (1 | 2 | 3), o2: 1, o3: 2, o4: (1 | 2 | 3 | *_|_), o5: (1 | *2 | 3), o6: (1 | 2 | 3), o7: (2 | 3), o8: (2 | 3), o9: (2 | 3), o10: (3 | *2), m1: (*2 | 3), m2: (*2 | 3), m3: (*2 | 3), m4: (*2 | 3), m5: (*2 | 3), i1: "c"} -- out/compile -- --- in.cue { o1: (1|2|3) o2: ((1|2|3) & 1) o3: (2 & (1|*2|3)) o4: ((1|*2|3) & (1|2|*3)) o5: ((1|*2|3) & (3|*2|1)) o6: ((1|2|3) & (3|1|2)) o7: ((1|2|3) & (2|3)) o8: ((1|2|3) & (3|2)) o9: ((2|3) & (1|2|3)) o10: ((3|2) & (1|*2|3)) m1: ((1|(*2|3)) & (>=2 & <=3)) m2: ((1|(*2|3)) & (2|3)) m3: ((*1|*(*2|3)) & (2|3)) m4: ((2|3) & (*2|3)) m5: ((*2|3) & (2|3)) i1: ([ 1, 2, ][3]|"c") } -- out/eval/stats -- Leaks: 1 Freed: 134 Reused: 126 Allocs: 9 Retain: 1 Unifications: 18 Conjuncts: 150 Disjuncts: 135 -- out/eval -- (struct){ o1: (int){ |((int){ 1 }, (int){ 2 }, (int){ 3 }) } o2: (int){ 1 } o3: (int){ 2 } o4: (int){ |((int){ 1 }, (int){ 2 }, (int){ 3 }) } o5: (int){ |(*(int){ 2 }, (int){ 1 }, (int){ 3 }) } o6: (int){ |((int){ 1 }, (int){ 2 }, (int){ 3 }) } o7: (int){ |((int){ 2 }, (int){ 3 }) } o8: (int){ |((int){ 2 }, (int){ 3 }) } o9: (int){ |((int){ 2 }, (int){ 3 }) } o10: (int){ |(*(int){ 2 }, (int){ 3 }) } m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } m4: (int){ |(*(int){ 2 }, (int){ 3 }) } m5: (int){ |(*(int){ 2 }, (int){ 3 }) } i1: (string){ "c" } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/015_types.txtar000066400000000000000000000043341474664451600243710ustar00rootroot00000000000000#name: types #evalPartial -- in.cue -- i: int j: int & 3 s: string t: "s" & string e: int & string e2: 1 & string b: !int p: +true m: -false -- out/def -- i: int j: 3 s: string t: "s" e: _|_ // conflicting values int and string (mismatched types int and string) e2: _|_ // conflicting values 1 and string (mismatched types int and string) b: _|_ // invalid operation !int (! int) p: _|_ // invalid operation +true (+ bool) m: _|_ // invalid operation -false (- bool) -- out/legacy-debug -- <0>{i: int, j: 3, s: string, t: "s", e: _|_((int & string):conflicting values int and string (mismatched types int and string)), e2: _|_((1 & string):conflicting values 1 and string (mismatched types int and string)), b: _|_(!int:invalid operation !int (! int)), p: _|_(+true:invalid operation +true (+ bool)), m: _|_(-false:invalid operation -false (- bool))} -- out/compile -- --- in.cue { i: int j: (int & 3) s: string t: ("s" & string) e: (int & string) e2: (1 & string) b: !int p: +true m: -false } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 8 Allocs: 2 Retain: 0 Unifications: 10 Conjuncts: 14 Disjuncts: 10 -- out/eval -- Errors: b: invalid operand int ('!' requires concrete value): ./in.cue:7:6 e: conflicting values int and string (mismatched types int and string): ./in.cue:5:5 ./in.cue:5:11 e2: conflicting values 1 and string (mismatched types int and string): ./in.cue:6:5 ./in.cue:6:9 p: invalid operation +true (+ bool): ./in.cue:8:5 m: invalid operation -false (- bool): ./in.cue:9:5 Result: (_|_){ // [eval] i: (int){ int } j: (int){ 3 } s: (string){ string } t: (string){ "s" } e: (_|_){ // [eval] e: conflicting values int and string (mismatched types int and string): // ./in.cue:5:5 // ./in.cue:5:11 } e2: (_|_){ // [eval] e2: conflicting values 1 and string (mismatched types int and string): // ./in.cue:6:5 // ./in.cue:6:9 } b: (_|_){ // [eval] b: invalid operand int ('!' requires concrete value): // ./in.cue:7:6 } p: (_|_){ // [eval] p: invalid operation +true (+ bool): // ./in.cue:8:5 } m: (_|_){ // [eval] m: invalid operation -false (- bool): // ./in.cue:9:5 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/016_comparison.txtar000066400000000000000000000024111474664451600253720ustar00rootroot00000000000000#name: comparison #evalPartial -- in.cue -- lss: 1 < 2 leq: 1 <= 1.0 leq: 2.0 <= 3 eql: 1 == 1.0 neq: 1.0 == 1 gtr: !(2 > 3) geq: 2.0 >= 2 seq: "a"+"b" == "ab" err: 2 == "s" -- out/def -- lss: true leq: true eql: true neq: true gtr: true geq: true seq: true err: _|_ // invalid operation 2 == "s" (mismatched types int and string) -- out/legacy-debug -- <0>{lss: true, leq: true, eql: true, neq: true, gtr: true, geq: true, seq: true, err: _|_((2 == "s"):invalid operation 2 == "s" (mismatched types int and string))} -- out/compile -- --- in.cue { lss: (1 < 2) leq: (1 <= 1.0) leq: (2.0 <= 3) eql: (1 == 1.0) neq: (1.0 == 1) gtr: !(2 > 3) geq: (2.0 >= 2) seq: (("a" + "b") == "ab") err: (2 == "s") } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 7 Allocs: 2 Retain: 0 Unifications: 9 Conjuncts: 10 Disjuncts: 9 -- out/eval -- Errors: err: invalid operands 2 and "s" to '==' (type int and string): ./in.cue:9:6 ./in.cue:9:11 Result: (_|_){ // [eval] lss: (bool){ true } leq: (bool){ true } eql: (bool){ true } neq: (bool){ true } gtr: (bool){ true } geq: (bool){ true } seq: (bool){ true } err: (_|_){ // [eval] err: invalid operands 2 and "s" to '==' (type int and string): // ./in.cue:9:6 // ./in.cue:9:11 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/017_null.txtar000066400000000000000000000021361474664451600241770ustar00rootroot00000000000000#name: null #evalPartial -- in.cue -- eql: null == null neq: null != null unf: null & null // errors eq1: null == 1 eq2: 1 == null ne1: "s" != null call: null() -- out/def -- eql: true neq: false unf: null // errors eq1: false eq2: false ne1: true call: _|_ // cannot call non-function null (type null) -- out/legacy-debug -- <0>{eql: true, neq: false, unf: null, eq1: false, eq2: false, ne1: true, call: _|_(null:cannot call non-function null (type null))} -- out/compile -- --- in.cue { eql: (null == null) neq: (null != null) unf: (null & null) eq1: (null == 1) eq2: (1 == null) ne1: ("s" != null) call: null() } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 6 Allocs: 2 Retain: 0 Unifications: 8 Conjuncts: 9 Disjuncts: 8 -- out/eval -- Errors: call: cannot call non-function null (type null): ./in.cue:9:7 Result: (_|_){ // [eval] eql: (bool){ true } neq: (bool){ false } unf: (null){ null } eq1: (bool){ false } eq2: (bool){ false } ne1: (bool){ true } call: (_|_){ // [eval] call: cannot call non-function null (type null): // ./in.cue:9:7 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/018_self-reference_cycles.txtar000066400000000000000000000023231474664451600274530ustar00rootroot00000000000000#name: self-reference cycles #evalPartial -- in.cue -- a: b - 100 b: a + 100 c: [c[1], c[0]] -- out/def -- a: b - 100 b: a + 100 c: [c[1], c[0]] -- out/legacy-debug -- <0>{a: (<1>.b - 100), b: (<1>.a + 100), c: [<1>.c[1],<1>.c[0]]} -- out/compile -- --- in.cue { a: (〈0;b〉 - 100) b: (〈0;a〉 + 100) c: [ 〈1;c〉[1], 〈1;c〉[0], ] } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 2 Allocs: 4 Retain: 11 Unifications: 6 Conjuncts: 26 Disjuncts: 7 -- out/evalalpha -- (struct){ a: (_|_){ // [cycle] cycle error: // ./in.cue:2:4 } b: (_|_){ // [cycle] cycle error: // ./in.cue:2:4 } c: (#list){ 0: (_){ _ } 1: (_){ _ } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,11 +1,11 @@ (struct){ a: (_|_){ // [cycle] cycle error: - // ./in.cue:1:4 + // ./in.cue:2:4 } b: (_|_){ // [cycle] cycle error: - // ./in.cue:1:4 + // ./in.cue:2:4 } c: (#list){ 0: (_){ _ } -- out/eval -- (struct){ a: (_|_){ // [cycle] cycle error: // ./in.cue:1:4 } b: (_|_){ // [cycle] cycle error: // ./in.cue:1:4 } c: (#list){ 0: (_){ _ } 1: (_){ _ } } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/019_resolved_self-reference_cycles.txtar000066400000000000000000000144251474664451600313650ustar00rootroot00000000000000#name: resolved self-reference cycles #evalPartial -- in.cue -- math: p1: { a: b - 100 b: a + 100 b: 200 } math: p2: { a: b - 100 b: 200 b: a + 100 } math: p3: { b: a + 100 a: b - 100 b: 200 } math: p4: { b: a + 100 b: 200 a: b - 100 } math: p5: { b: 200 b: a + 100 a: b - 100 } math: p6: { b: 200 a: b - 100 b: a + 100 } a: 100 list: t0: c: [c[0]] list: t1: p1: c: [c[1], a] list: t1: p2: c: [a, c[0]] nodes: t1: p1: s1: s1 & {a: 1} nodes: t1: p2: s1: {a: 1} & s1 nodes: t2: { s1: s2 & {a: 1} s2: s1 & {b: 2} } nodes: t3: { s1: s2 & {a: 1} s2: s3 & {b: 2} s3: s1 & {c: 3} } -- out/def -- a: 100 b: 200 c: [100, 100] s1: s2 & { a: 1 } s2: s3 & { b: 2 } s3: s1 & { c: 3 } -- out/export -- a: 100 b: 200 c: [100, 100] s1: { a: 1 b: 2 c: 3 } s2: { a: 1 b: 2 c: 3 } s3: { a: 1 b: 2 c: 3 } -- out/yaml -- a: 100 b: 200 c: - 100 - 100 s1: a: 1 b: 2 c: 3 s2: a: 1 b: 2 c: 3 s3: a: 1 b: 2 c: 3 -- out/json -- {"a":100,"b":200,"c":[100,100],"s1":{"a":1,"b":2,"c":3},"s2":{"a":1,"b":2,"c":3},"s3":{"a":1,"b":2,"c":3}} -- out/legacy-debug -- <0>{a: 100, b: 200, c: [100,100], s1: <1>{a: 1, b: 2, c: 3}, s2: <2>{a: 1, b: 2, c: 3}, s3: <3>{a: 1, b: 2, c: 3}} -- out/compile -- --- in.cue { math: { p1: { a: (〈0;b〉 - 100) b: (〈0;a〉 + 100) b: 200 } } math: { p2: { a: (〈0;b〉 - 100) b: 200 b: (〈0;a〉 + 100) } } math: { p3: { b: (〈0;a〉 + 100) a: (〈0;b〉 - 100) b: 200 } } math: { p4: { b: (〈0;a〉 + 100) b: 200 a: (〈0;b〉 - 100) } } math: { p5: { b: 200 b: (〈0;a〉 + 100) a: (〈0;b〉 - 100) } } math: { p6: { b: 200 a: (〈0;b〉 - 100) b: (〈0;a〉 + 100) } } a: 100 list: { t0: { c: [ 〈1;c〉[0], ] } } list: { t1: { p1: { c: [ 〈1;c〉[1], 〈4;a〉, ] } } } list: { t1: { p2: { c: [ 〈4;a〉, 〈1;c〉[0], ] } } } nodes: { t1: { p1: { s1: (〈0;s1〉 & { a: 1 }) } } } nodes: { t1: { p2: { s1: ({ a: 1 } & 〈0;s1〉) } } } nodes: { t2: { s1: (〈0;s2〉 & { a: 1 }) s2: (〈0;s1〉 & { b: 2 }) } } nodes: { t3: { s1: (〈0;s2〉 & { a: 1 }) s2: (〈0;s3〉 & { b: 2 }) s3: (〈0;s1〉 & { c: 3 }) } } } -- out/eval/stats -- Leaks: 0 Freed: 62 Reused: 55 Allocs: 7 Retain: 10 Unifications: 62 Conjuncts: 105 Disjuncts: 70 -- out/evalalpha -- (struct){ math: (struct){ p1: (struct){ a: (int){ 100 } b: (int){ 200 } } p2: (struct){ a: (int){ 100 } b: (int){ 200 } } p3: (struct){ b: (int){ 200 } a: (int){ 100 } } p4: (struct){ b: (int){ 200 } a: (int){ 100 } } p5: (struct){ b: (int){ 200 } a: (int){ 100 } } p6: (struct){ b: (int){ 200 } a: (int){ 100 } } } a: (int){ 100 } list: (struct){ t0: (struct){ c: (#list){ 0: (_){ _ } } } t1: (struct){ p1: (struct){ c: (#list){ 0: (int){ 100 } 1: (int){ 100 } } } p2: (struct){ c: (#list){ 0: (int){ 100 } 1: (int){ 100 } } } } } nodes: (struct){ t1: (struct){ p1: (struct){ s1: (struct){ a: (int){ 1 } } } p2: (struct){ s1: (struct){ a: (int){ 1 } } } } t2: (struct){ s1: (struct){ a: (int){ 1 } b: (int){ 2 } } s2: (struct){ b: (int){ 2 } a: (int){ 1 } } } t3: (struct){ s1: (struct){ a: (int){ 1 } b: (int){ 2 } c: (int){ 3 } } s2: (struct){ b: (int){ 2 } c: (int){ 3 } a: (int){ 1 } } s3: (struct){ c: (int){ 3 } a: (int){ 1 } b: (int){ 2 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -73,18 +73,18 @@ t3: (struct){ s1: (struct){ a: (int){ 1 } - c: (int){ 3 } - b: (int){ 2 } - } - s2: (struct){ - b: (int){ 2 } - a: (int){ 1 } - c: (int){ 3 } + b: (int){ 2 } + c: (int){ 3 } + } + s2: (struct){ + b: (int){ 2 } + c: (int){ 3 } + a: (int){ 1 } } s3: (struct){ c: (int){ 3 } - b: (int){ 2 } - a: (int){ 1 } + a: (int){ 1 } + b: (int){ 2 } } } } -- diff/explanation -- Reordering. -- out/eval -- (struct){ math: (struct){ p1: (struct){ a: (int){ 100 } b: (int){ 200 } } p2: (struct){ a: (int){ 100 } b: (int){ 200 } } p3: (struct){ b: (int){ 200 } a: (int){ 100 } } p4: (struct){ b: (int){ 200 } a: (int){ 100 } } p5: (struct){ b: (int){ 200 } a: (int){ 100 } } p6: (struct){ b: (int){ 200 } a: (int){ 100 } } } a: (int){ 100 } list: (struct){ t0: (struct){ c: (#list){ 0: (_){ _ } } } t1: (struct){ p1: (struct){ c: (#list){ 0: (int){ 100 } 1: (int){ 100 } } } p2: (struct){ c: (#list){ 0: (int){ 100 } 1: (int){ 100 } } } } } nodes: (struct){ t1: (struct){ p1: (struct){ s1: (struct){ a: (int){ 1 } } } p2: (struct){ s1: (struct){ a: (int){ 1 } } } } t2: (struct){ s1: (struct){ a: (int){ 1 } b: (int){ 2 } } s2: (struct){ b: (int){ 2 } a: (int){ 1 } } } t3: (struct){ s1: (struct){ a: (int){ 1 } c: (int){ 3 } b: (int){ 2 } } s2: (struct){ b: (int){ 2 } a: (int){ 1 } c: (int){ 3 } } s3: (struct){ c: (int){ 3 } b: (int){ 2 } a: (int){ 1 } } } } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/020_resolved_self-reference_cycles__Issue_19.txtar000066400000000000000000000017401474664451600331710ustar00rootroot00000000000000#name: resolved self-reference cycles: Issue 19 #evalPartial -- in.cue -- // CUE knows how to resolve the following: x: y + 100 y: x - 100 x: 200 z1: z2 + 1 z2: z3 + 2 z3: z1 - 3 z3: 8 // TODO: extensive tests with disjunctions. -- out/def -- // CUE knows how to resolve the following: x: 200 y: 100 z1: 11 z2: 10 z3: 8 -- out/export -- // CUE knows how to resolve the following: x: 200 y: 100 z1: 11 z2: 10 z3: 8 -- out/yaml -- x: 200 y: 100 z1: 11 z2: 10 z3: 8 -- out/json -- {"x":200,"y":100,"z1":11,"z2":10,"z3":8} -- out/legacy-debug -- <0>{x: 200, y: 100, z1: 11, z2: 10, z3: 8} -- out/compile -- --- in.cue { x: (〈0;y〉 + 100) y: (〈0;x〉 - 100) x: 200 z1: (〈0;z2〉 + 1) z2: (〈0;z3〉 + 2) z3: (〈0;z1〉 - 3) z3: 8 } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 2 Allocs: 4 Retain: 3 Unifications: 6 Conjuncts: 6 Disjuncts: 8 -- out/eval -- (struct){ x: (int){ 200 } y: (int){ 100 } z1: (int){ 11 } z2: (int){ 10 } z3: (int){ 8 } } cue-lang-cue-db9cc73/cue/testdata/basicrewrite/aliases/000077500000000000000000000000001474664451600231715ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/basicrewrite/aliases/aliases.txtar000066400000000000000000000010761474664451600257020ustar00rootroot00000000000000-- in.cue -- t0: { a=_a: _ let _b = a _out: _b } t1: { _a: b let b = c c=d: 3 } -- out/compile -- --- in.cue { t0: { _a: _ let _b#1 = 〈0;_a〉 _out: 〈0;let _b#1〉 } t1: { _a: 〈0;let b#2〉 let b#2 = 〈0;d〉 d: 3 } } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 4 Allocs: 5 Retain: 3 Unifications: 9 Conjuncts: 14 Disjuncts: 10 -- out/eval -- (struct){ t0: (struct){ _a: (_){ _ } let _b#1 = (_){ _ } _out: (_){ _ } } t1: (struct){ _a: (int){ 3 } let b#2 = (int){ 3 } d: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/000077500000000000000000000000001474664451600212025ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/benchmarks/chain.txtar000066400000000000000000001657431474664451600233700ustar00rootroot00000000000000// TODO(perf): reduce number of Conjunctions -- stats.txt -- Leaks: 0 Freed: 1001 Reused: 999 Allocs: 2 Retain: 0 Unifications: 1001 Conjuncts: 500501 Disjuncts: 1001 -- in.cue -- f1: string f2: f1 f3: f2 f4: f3 f5: f4 f6: f5 f7: f6 f8: f7 f9: f8 f10: f9 f11: f10 f12: f11 f13: f12 f14: f13 f15: f14 f16: f15 f17: f16 f18: f17 f19: f18 f20: f19 f21: f20 f22: f21 f23: f22 f24: f23 f25: f24 f26: f25 f27: f26 f28: f27 f29: f28 f30: f29 f31: f30 f32: f31 f33: f32 f34: f33 f35: f34 f36: f35 f37: f36 f38: f37 f39: f38 f40: f39 f41: f40 f42: f41 f43: f42 f44: f43 f45: f44 f46: f45 f47: f46 f48: f47 f49: f48 f50: f49 f51: f50 f52: f51 f53: f52 f54: f53 f55: f54 f56: f55 f57: f56 f58: f57 f59: f58 f60: f59 f61: f60 f62: f61 f63: f62 f64: f63 f65: f64 f66: f65 f67: f66 f68: f67 f69: f68 f70: f69 f71: f70 f72: f71 f73: f72 f74: f73 f75: f74 f76: f75 f77: f76 f78: f77 f79: f78 f80: f79 f81: f80 f82: f81 f83: f82 f84: f83 f85: f84 f86: f85 f87: f86 f88: f87 f89: f88 f90: f89 f91: f90 f92: f91 f93: f92 f94: f93 f95: f94 f96: f95 f97: f96 f98: f97 f99: f98 f100: f99 f101: f100 f102: f101 f103: f102 f104: f103 f105: f104 f106: f105 f107: f106 f108: f107 f109: f108 f110: f109 f111: f110 f112: f111 f113: f112 f114: f113 f115: f114 f116: f115 f117: f116 f118: f117 f119: f118 f120: f119 f121: f120 f122: f121 f123: f122 f124: f123 f125: f124 f126: f125 f127: f126 f128: f127 f129: f128 f130: f129 f131: f130 f132: f131 f133: f132 f134: f133 f135: f134 f136: f135 f137: f136 f138: f137 f139: f138 f140: f139 f141: f140 f142: f141 f143: f142 f144: f143 f145: f144 f146: f145 f147: f146 f148: f147 f149: f148 f150: f149 f151: f150 f152: f151 f153: f152 f154: f153 f155: f154 f156: f155 f157: f156 f158: f157 f159: f158 f160: f159 f161: f160 f162: f161 f163: f162 f164: f163 f165: f164 f166: f165 f167: f166 f168: f167 f169: f168 f170: f169 f171: f170 f172: f171 f173: f172 f174: f173 f175: f174 f176: f175 f177: f176 f178: f177 f179: f178 f180: f179 f181: f180 f182: f181 f183: f182 f184: f183 f185: f184 f186: f185 f187: f186 f188: f187 f189: f188 f190: f189 f191: f190 f192: f191 f193: f192 f194: f193 f195: f194 f196: f195 f197: f196 f198: f197 f199: f198 f200: f199 f201: f200 f202: f201 f203: f202 f204: f203 f205: f204 f206: f205 f207: f206 f208: f207 f209: f208 f210: f209 f211: f210 f212: f211 f213: f212 f214: f213 f215: f214 f216: f215 f217: f216 f218: f217 f219: f218 f220: f219 f221: f220 f222: f221 f223: f222 f224: f223 f225: f224 f226: f225 f227: f226 f228: f227 f229: f228 f230: f229 f231: f230 f232: f231 f233: f232 f234: f233 f235: f234 f236: f235 f237: f236 f238: f237 f239: f238 f240: f239 f241: f240 f242: f241 f243: f242 f244: f243 f245: f244 f246: f245 f247: f246 f248: f247 f249: f248 f250: f249 f251: f250 f252: f251 f253: f252 f254: f253 f255: f254 f256: f255 f257: f256 f258: f257 f259: f258 f260: f259 f261: f260 f262: f261 f263: f262 f264: f263 f265: f264 f266: f265 f267: f266 f268: f267 f269: f268 f270: f269 f271: f270 f272: f271 f273: f272 f274: f273 f275: f274 f276: f275 f277: f276 f278: f277 f279: f278 f280: f279 f281: f280 f282: f281 f283: f282 f284: f283 f285: f284 f286: f285 f287: f286 f288: f287 f289: f288 f290: f289 f291: f290 f292: f291 f293: f292 f294: f293 f295: f294 f296: f295 f297: f296 f298: f297 f299: f298 f300: f299 f301: f300 f302: f301 f303: f302 f304: f303 f305: f304 f306: f305 f307: f306 f308: f307 f309: f308 f310: f309 f311: f310 f312: f311 f313: f312 f314: f313 f315: f314 f316: f315 f317: f316 f318: f317 f319: f318 f320: f319 f321: f320 f322: f321 f323: f322 f324: f323 f325: f324 f326: f325 f327: f326 f328: f327 f329: f328 f330: f329 f331: f330 f332: f331 f333: f332 f334: f333 f335: f334 f336: f335 f337: f336 f338: f337 f339: f338 f340: f339 f341: f340 f342: f341 f343: f342 f344: f343 f345: f344 f346: f345 f347: f346 f348: f347 f349: f348 f350: f349 f351: f350 f352: f351 f353: f352 f354: f353 f355: f354 f356: f355 f357: f356 f358: f357 f359: f358 f360: f359 f361: f360 f362: f361 f363: f362 f364: f363 f365: f364 f366: f365 f367: f366 f368: f367 f369: f368 f370: f369 f371: f370 f372: f371 f373: f372 f374: f373 f375: f374 f376: f375 f377: f376 f378: f377 f379: f378 f380: f379 f381: f380 f382: f381 f383: f382 f384: f383 f385: f384 f386: f385 f387: f386 f388: f387 f389: f388 f390: f389 f391: f390 f392: f391 f393: f392 f394: f393 f395: f394 f396: f395 f397: f396 f398: f397 f399: f398 f400: f399 f401: f400 f402: f401 f403: f402 f404: f403 f405: f404 f406: f405 f407: f406 f408: f407 f409: f408 f410: f409 f411: f410 f412: f411 f413: f412 f414: f413 f415: f414 f416: f415 f417: f416 f418: f417 f419: f418 f420: f419 f421: f420 f422: f421 f423: f422 f424: f423 f425: f424 f426: f425 f427: f426 f428: f427 f429: f428 f430: f429 f431: f430 f432: f431 f433: f432 f434: f433 f435: f434 f436: f435 f437: f436 f438: f437 f439: f438 f440: f439 f441: f440 f442: f441 f443: f442 f444: f443 f445: f444 f446: f445 f447: f446 f448: f447 f449: f448 f450: f449 f451: f450 f452: f451 f453: f452 f454: f453 f455: f454 f456: f455 f457: f456 f458: f457 f459: f458 f460: f459 f461: f460 f462: f461 f463: f462 f464: f463 f465: f464 f466: f465 f467: f466 f468: f467 f469: f468 f470: f469 f471: f470 f472: f471 f473: f472 f474: f473 f475: f474 f476: f475 f477: f476 f478: f477 f479: f478 f480: f479 f481: f480 f482: f481 f483: f482 f484: f483 f485: f484 f486: f485 f487: f486 f488: f487 f489: f488 f490: f489 f491: f490 f492: f491 f493: f492 f494: f493 f495: f494 f496: f495 f497: f496 f498: f497 f499: f498 f500: f499 f501: f500 f502: f501 f503: f502 f504: f503 f505: f504 f506: f505 f507: f506 f508: f507 f509: f508 f510: f509 f511: f510 f512: f511 f513: f512 f514: f513 f515: f514 f516: f515 f517: f516 f518: f517 f519: f518 f520: f519 f521: f520 f522: f521 f523: f522 f524: f523 f525: f524 f526: f525 f527: f526 f528: f527 f529: f528 f530: f529 f531: f530 f532: f531 f533: f532 f534: f533 f535: f534 f536: f535 f537: f536 f538: f537 f539: f538 f540: f539 f541: f540 f542: f541 f543: f542 f544: f543 f545: f544 f546: f545 f547: f546 f548: f547 f549: f548 f550: f549 f551: f550 f552: f551 f553: f552 f554: f553 f555: f554 f556: f555 f557: f556 f558: f557 f559: f558 f560: f559 f561: f560 f562: f561 f563: f562 f564: f563 f565: f564 f566: f565 f567: f566 f568: f567 f569: f568 f570: f569 f571: f570 f572: f571 f573: f572 f574: f573 f575: f574 f576: f575 f577: f576 f578: f577 f579: f578 f580: f579 f581: f580 f582: f581 f583: f582 f584: f583 f585: f584 f586: f585 f587: f586 f588: f587 f589: f588 f590: f589 f591: f590 f592: f591 f593: f592 f594: f593 f595: f594 f596: f595 f597: f596 f598: f597 f599: f598 f600: f599 f601: f600 f602: f601 f603: f602 f604: f603 f605: f604 f606: f605 f607: f606 f608: f607 f609: f608 f610: f609 f611: f610 f612: f611 f613: f612 f614: f613 f615: f614 f616: f615 f617: f616 f618: f617 f619: f618 f620: f619 f621: f620 f622: f621 f623: f622 f624: f623 f625: f624 f626: f625 f627: f626 f628: f627 f629: f628 f630: f629 f631: f630 f632: f631 f633: f632 f634: f633 f635: f634 f636: f635 f637: f636 f638: f637 f639: f638 f640: f639 f641: f640 f642: f641 f643: f642 f644: f643 f645: f644 f646: f645 f647: f646 f648: f647 f649: f648 f650: f649 f651: f650 f652: f651 f653: f652 f654: f653 f655: f654 f656: f655 f657: f656 f658: f657 f659: f658 f660: f659 f661: f660 f662: f661 f663: f662 f664: f663 f665: f664 f666: f665 f667: f666 f668: f667 f669: f668 f670: f669 f671: f670 f672: f671 f673: f672 f674: f673 f675: f674 f676: f675 f677: f676 f678: f677 f679: f678 f680: f679 f681: f680 f682: f681 f683: f682 f684: f683 f685: f684 f686: f685 f687: f686 f688: f687 f689: f688 f690: f689 f691: f690 f692: f691 f693: f692 f694: f693 f695: f694 f696: f695 f697: f696 f698: f697 f699: f698 f700: f699 f701: f700 f702: f701 f703: f702 f704: f703 f705: f704 f706: f705 f707: f706 f708: f707 f709: f708 f710: f709 f711: f710 f712: f711 f713: f712 f714: f713 f715: f714 f716: f715 f717: f716 f718: f717 f719: f718 f720: f719 f721: f720 f722: f721 f723: f722 f724: f723 f725: f724 f726: f725 f727: f726 f728: f727 f729: f728 f730: f729 f731: f730 f732: f731 f733: f732 f734: f733 f735: f734 f736: f735 f737: f736 f738: f737 f739: f738 f740: f739 f741: f740 f742: f741 f743: f742 f744: f743 f745: f744 f746: f745 f747: f746 f748: f747 f749: f748 f750: f749 f751: f750 f752: f751 f753: f752 f754: f753 f755: f754 f756: f755 f757: f756 f758: f757 f759: f758 f760: f759 f761: f760 f762: f761 f763: f762 f764: f763 f765: f764 f766: f765 f767: f766 f768: f767 f769: f768 f770: f769 f771: f770 f772: f771 f773: f772 f774: f773 f775: f774 f776: f775 f777: f776 f778: f777 f779: f778 f780: f779 f781: f780 f782: f781 f783: f782 f784: f783 f785: f784 f786: f785 f787: f786 f788: f787 f789: f788 f790: f789 f791: f790 f792: f791 f793: f792 f794: f793 f795: f794 f796: f795 f797: f796 f798: f797 f799: f798 f800: f799 f801: f800 f802: f801 f803: f802 f804: f803 f805: f804 f806: f805 f807: f806 f808: f807 f809: f808 f810: f809 f811: f810 f812: f811 f813: f812 f814: f813 f815: f814 f816: f815 f817: f816 f818: f817 f819: f818 f820: f819 f821: f820 f822: f821 f823: f822 f824: f823 f825: f824 f826: f825 f827: f826 f828: f827 f829: f828 f830: f829 f831: f830 f832: f831 f833: f832 f834: f833 f835: f834 f836: f835 f837: f836 f838: f837 f839: f838 f840: f839 f841: f840 f842: f841 f843: f842 f844: f843 f845: f844 f846: f845 f847: f846 f848: f847 f849: f848 f850: f849 f851: f850 f852: f851 f853: f852 f854: f853 f855: f854 f856: f855 f857: f856 f858: f857 f859: f858 f860: f859 f861: f860 f862: f861 f863: f862 f864: f863 f865: f864 f866: f865 f867: f866 f868: f867 f869: f868 f870: f869 f871: f870 f872: f871 f873: f872 f874: f873 f875: f874 f876: f875 f877: f876 f878: f877 f879: f878 f880: f879 f881: f880 f882: f881 f883: f882 f884: f883 f885: f884 f886: f885 f887: f886 f888: f887 f889: f888 f890: f889 f891: f890 f892: f891 f893: f892 f894: f893 f895: f894 f896: f895 f897: f896 f898: f897 f899: f898 f900: f899 f901: f900 f902: f901 f903: f902 f904: f903 f905: f904 f906: f905 f907: f906 f908: f907 f909: f908 f910: f909 f911: f910 f912: f911 f913: f912 f914: f913 f915: f914 f916: f915 f917: f916 f918: f917 f919: f918 f920: f919 f921: f920 f922: f921 f923: f922 f924: f923 f925: f924 f926: f925 f927: f926 f928: f927 f929: f928 f930: f929 f931: f930 f932: f931 f933: f932 f934: f933 f935: f934 f936: f935 f937: f936 f938: f937 f939: f938 f940: f939 f941: f940 f942: f941 f943: f942 f944: f943 f945: f944 f946: f945 f947: f946 f948: f947 f949: f948 f950: f949 f951: f950 f952: f951 f953: f952 f954: f953 f955: f954 f956: f955 f957: f956 f958: f957 f959: f958 f960: f959 f961: f960 f962: f961 f963: f962 f964: f963 f965: f964 f966: f965 f967: f966 f968: f967 f969: f968 f970: f969 f971: f970 f972: f971 f973: f972 f974: f973 f975: f974 f976: f975 f977: f976 f978: f977 f979: f978 f980: f979 f981: f980 f982: f981 f983: f982 f984: f983 f985: f984 f986: f985 f987: f986 f988: f987 f989: f988 f990: f989 f991: f990 f992: f991 f993: f992 f994: f993 f995: f994 f996: f995 f997: f996 f998: f997 f999: f998 f1000: f999 -- out/compile -- --- in.cue { f1: string f2: 〈0;f1〉 f3: 〈0;f2〉 f4: 〈0;f3〉 f5: 〈0;f4〉 f6: 〈0;f5〉 f7: 〈0;f6〉 f8: 〈0;f7〉 f9: 〈0;f8〉 f10: 〈0;f9〉 f11: 〈0;f10〉 f12: 〈0;f11〉 f13: 〈0;f12〉 f14: 〈0;f13〉 f15: 〈0;f14〉 f16: 〈0;f15〉 f17: 〈0;f16〉 f18: 〈0;f17〉 f19: 〈0;f18〉 f20: 〈0;f19〉 f21: 〈0;f20〉 f22: 〈0;f21〉 f23: 〈0;f22〉 f24: 〈0;f23〉 f25: 〈0;f24〉 f26: 〈0;f25〉 f27: 〈0;f26〉 f28: 〈0;f27〉 f29: 〈0;f28〉 f30: 〈0;f29〉 f31: 〈0;f30〉 f32: 〈0;f31〉 f33: 〈0;f32〉 f34: 〈0;f33〉 f35: 〈0;f34〉 f36: 〈0;f35〉 f37: 〈0;f36〉 f38: 〈0;f37〉 f39: 〈0;f38〉 f40: 〈0;f39〉 f41: 〈0;f40〉 f42: 〈0;f41〉 f43: 〈0;f42〉 f44: 〈0;f43〉 f45: 〈0;f44〉 f46: 〈0;f45〉 f47: 〈0;f46〉 f48: 〈0;f47〉 f49: 〈0;f48〉 f50: 〈0;f49〉 f51: 〈0;f50〉 f52: 〈0;f51〉 f53: 〈0;f52〉 f54: 〈0;f53〉 f55: 〈0;f54〉 f56: 〈0;f55〉 f57: 〈0;f56〉 f58: 〈0;f57〉 f59: 〈0;f58〉 f60: 〈0;f59〉 f61: 〈0;f60〉 f62: 〈0;f61〉 f63: 〈0;f62〉 f64: 〈0;f63〉 f65: 〈0;f64〉 f66: 〈0;f65〉 f67: 〈0;f66〉 f68: 〈0;f67〉 f69: 〈0;f68〉 f70: 〈0;f69〉 f71: 〈0;f70〉 f72: 〈0;f71〉 f73: 〈0;f72〉 f74: 〈0;f73〉 f75: 〈0;f74〉 f76: 〈0;f75〉 f77: 〈0;f76〉 f78: 〈0;f77〉 f79: 〈0;f78〉 f80: 〈0;f79〉 f81: 〈0;f80〉 f82: 〈0;f81〉 f83: 〈0;f82〉 f84: 〈0;f83〉 f85: 〈0;f84〉 f86: 〈0;f85〉 f87: 〈0;f86〉 f88: 〈0;f87〉 f89: 〈0;f88〉 f90: 〈0;f89〉 f91: 〈0;f90〉 f92: 〈0;f91〉 f93: 〈0;f92〉 f94: 〈0;f93〉 f95: 〈0;f94〉 f96: 〈0;f95〉 f97: 〈0;f96〉 f98: 〈0;f97〉 f99: 〈0;f98〉 f100: 〈0;f99〉 f101: 〈0;f100〉 f102: 〈0;f101〉 f103: 〈0;f102〉 f104: 〈0;f103〉 f105: 〈0;f104〉 f106: 〈0;f105〉 f107: 〈0;f106〉 f108: 〈0;f107〉 f109: 〈0;f108〉 f110: 〈0;f109〉 f111: 〈0;f110〉 f112: 〈0;f111〉 f113: 〈0;f112〉 f114: 〈0;f113〉 f115: 〈0;f114〉 f116: 〈0;f115〉 f117: 〈0;f116〉 f118: 〈0;f117〉 f119: 〈0;f118〉 f120: 〈0;f119〉 f121: 〈0;f120〉 f122: 〈0;f121〉 f123: 〈0;f122〉 f124: 〈0;f123〉 f125: 〈0;f124〉 f126: 〈0;f125〉 f127: 〈0;f126〉 f128: 〈0;f127〉 f129: 〈0;f128〉 f130: 〈0;f129〉 f131: 〈0;f130〉 f132: 〈0;f131〉 f133: 〈0;f132〉 f134: 〈0;f133〉 f135: 〈0;f134〉 f136: 〈0;f135〉 f137: 〈0;f136〉 f138: 〈0;f137〉 f139: 〈0;f138〉 f140: 〈0;f139〉 f141: 〈0;f140〉 f142: 〈0;f141〉 f143: 〈0;f142〉 f144: 〈0;f143〉 f145: 〈0;f144〉 f146: 〈0;f145〉 f147: 〈0;f146〉 f148: 〈0;f147〉 f149: 〈0;f148〉 f150: 〈0;f149〉 f151: 〈0;f150〉 f152: 〈0;f151〉 f153: 〈0;f152〉 f154: 〈0;f153〉 f155: 〈0;f154〉 f156: 〈0;f155〉 f157: 〈0;f156〉 f158: 〈0;f157〉 f159: 〈0;f158〉 f160: 〈0;f159〉 f161: 〈0;f160〉 f162: 〈0;f161〉 f163: 〈0;f162〉 f164: 〈0;f163〉 f165: 〈0;f164〉 f166: 〈0;f165〉 f167: 〈0;f166〉 f168: 〈0;f167〉 f169: 〈0;f168〉 f170: 〈0;f169〉 f171: 〈0;f170〉 f172: 〈0;f171〉 f173: 〈0;f172〉 f174: 〈0;f173〉 f175: 〈0;f174〉 f176: 〈0;f175〉 f177: 〈0;f176〉 f178: 〈0;f177〉 f179: 〈0;f178〉 f180: 〈0;f179〉 f181: 〈0;f180〉 f182: 〈0;f181〉 f183: 〈0;f182〉 f184: 〈0;f183〉 f185: 〈0;f184〉 f186: 〈0;f185〉 f187: 〈0;f186〉 f188: 〈0;f187〉 f189: 〈0;f188〉 f190: 〈0;f189〉 f191: 〈0;f190〉 f192: 〈0;f191〉 f193: 〈0;f192〉 f194: 〈0;f193〉 f195: 〈0;f194〉 f196: 〈0;f195〉 f197: 〈0;f196〉 f198: 〈0;f197〉 f199: 〈0;f198〉 f200: 〈0;f199〉 f201: 〈0;f200〉 f202: 〈0;f201〉 f203: 〈0;f202〉 f204: 〈0;f203〉 f205: 〈0;f204〉 f206: 〈0;f205〉 f207: 〈0;f206〉 f208: 〈0;f207〉 f209: 〈0;f208〉 f210: 〈0;f209〉 f211: 〈0;f210〉 f212: 〈0;f211〉 f213: 〈0;f212〉 f214: 〈0;f213〉 f215: 〈0;f214〉 f216: 〈0;f215〉 f217: 〈0;f216〉 f218: 〈0;f217〉 f219: 〈0;f218〉 f220: 〈0;f219〉 f221: 〈0;f220〉 f222: 〈0;f221〉 f223: 〈0;f222〉 f224: 〈0;f223〉 f225: 〈0;f224〉 f226: 〈0;f225〉 f227: 〈0;f226〉 f228: 〈0;f227〉 f229: 〈0;f228〉 f230: 〈0;f229〉 f231: 〈0;f230〉 f232: 〈0;f231〉 f233: 〈0;f232〉 f234: 〈0;f233〉 f235: 〈0;f234〉 f236: 〈0;f235〉 f237: 〈0;f236〉 f238: 〈0;f237〉 f239: 〈0;f238〉 f240: 〈0;f239〉 f241: 〈0;f240〉 f242: 〈0;f241〉 f243: 〈0;f242〉 f244: 〈0;f243〉 f245: 〈0;f244〉 f246: 〈0;f245〉 f247: 〈0;f246〉 f248: 〈0;f247〉 f249: 〈0;f248〉 f250: 〈0;f249〉 f251: 〈0;f250〉 f252: 〈0;f251〉 f253: 〈0;f252〉 f254: 〈0;f253〉 f255: 〈0;f254〉 f256: 〈0;f255〉 f257: 〈0;f256〉 f258: 〈0;f257〉 f259: 〈0;f258〉 f260: 〈0;f259〉 f261: 〈0;f260〉 f262: 〈0;f261〉 f263: 〈0;f262〉 f264: 〈0;f263〉 f265: 〈0;f264〉 f266: 〈0;f265〉 f267: 〈0;f266〉 f268: 〈0;f267〉 f269: 〈0;f268〉 f270: 〈0;f269〉 f271: 〈0;f270〉 f272: 〈0;f271〉 f273: 〈0;f272〉 f274: 〈0;f273〉 f275: 〈0;f274〉 f276: 〈0;f275〉 f277: 〈0;f276〉 f278: 〈0;f277〉 f279: 〈0;f278〉 f280: 〈0;f279〉 f281: 〈0;f280〉 f282: 〈0;f281〉 f283: 〈0;f282〉 f284: 〈0;f283〉 f285: 〈0;f284〉 f286: 〈0;f285〉 f287: 〈0;f286〉 f288: 〈0;f287〉 f289: 〈0;f288〉 f290: 〈0;f289〉 f291: 〈0;f290〉 f292: 〈0;f291〉 f293: 〈0;f292〉 f294: 〈0;f293〉 f295: 〈0;f294〉 f296: 〈0;f295〉 f297: 〈0;f296〉 f298: 〈0;f297〉 f299: 〈0;f298〉 f300: 〈0;f299〉 f301: 〈0;f300〉 f302: 〈0;f301〉 f303: 〈0;f302〉 f304: 〈0;f303〉 f305: 〈0;f304〉 f306: 〈0;f305〉 f307: 〈0;f306〉 f308: 〈0;f307〉 f309: 〈0;f308〉 f310: 〈0;f309〉 f311: 〈0;f310〉 f312: 〈0;f311〉 f313: 〈0;f312〉 f314: 〈0;f313〉 f315: 〈0;f314〉 f316: 〈0;f315〉 f317: 〈0;f316〉 f318: 〈0;f317〉 f319: 〈0;f318〉 f320: 〈0;f319〉 f321: 〈0;f320〉 f322: 〈0;f321〉 f323: 〈0;f322〉 f324: 〈0;f323〉 f325: 〈0;f324〉 f326: 〈0;f325〉 f327: 〈0;f326〉 f328: 〈0;f327〉 f329: 〈0;f328〉 f330: 〈0;f329〉 f331: 〈0;f330〉 f332: 〈0;f331〉 f333: 〈0;f332〉 f334: 〈0;f333〉 f335: 〈0;f334〉 f336: 〈0;f335〉 f337: 〈0;f336〉 f338: 〈0;f337〉 f339: 〈0;f338〉 f340: 〈0;f339〉 f341: 〈0;f340〉 f342: 〈0;f341〉 f343: 〈0;f342〉 f344: 〈0;f343〉 f345: 〈0;f344〉 f346: 〈0;f345〉 f347: 〈0;f346〉 f348: 〈0;f347〉 f349: 〈0;f348〉 f350: 〈0;f349〉 f351: 〈0;f350〉 f352: 〈0;f351〉 f353: 〈0;f352〉 f354: 〈0;f353〉 f355: 〈0;f354〉 f356: 〈0;f355〉 f357: 〈0;f356〉 f358: 〈0;f357〉 f359: 〈0;f358〉 f360: 〈0;f359〉 f361: 〈0;f360〉 f362: 〈0;f361〉 f363: 〈0;f362〉 f364: 〈0;f363〉 f365: 〈0;f364〉 f366: 〈0;f365〉 f367: 〈0;f366〉 f368: 〈0;f367〉 f369: 〈0;f368〉 f370: 〈0;f369〉 f371: 〈0;f370〉 f372: 〈0;f371〉 f373: 〈0;f372〉 f374: 〈0;f373〉 f375: 〈0;f374〉 f376: 〈0;f375〉 f377: 〈0;f376〉 f378: 〈0;f377〉 f379: 〈0;f378〉 f380: 〈0;f379〉 f381: 〈0;f380〉 f382: 〈0;f381〉 f383: 〈0;f382〉 f384: 〈0;f383〉 f385: 〈0;f384〉 f386: 〈0;f385〉 f387: 〈0;f386〉 f388: 〈0;f387〉 f389: 〈0;f388〉 f390: 〈0;f389〉 f391: 〈0;f390〉 f392: 〈0;f391〉 f393: 〈0;f392〉 f394: 〈0;f393〉 f395: 〈0;f394〉 f396: 〈0;f395〉 f397: 〈0;f396〉 f398: 〈0;f397〉 f399: 〈0;f398〉 f400: 〈0;f399〉 f401: 〈0;f400〉 f402: 〈0;f401〉 f403: 〈0;f402〉 f404: 〈0;f403〉 f405: 〈0;f404〉 f406: 〈0;f405〉 f407: 〈0;f406〉 f408: 〈0;f407〉 f409: 〈0;f408〉 f410: 〈0;f409〉 f411: 〈0;f410〉 f412: 〈0;f411〉 f413: 〈0;f412〉 f414: 〈0;f413〉 f415: 〈0;f414〉 f416: 〈0;f415〉 f417: 〈0;f416〉 f418: 〈0;f417〉 f419: 〈0;f418〉 f420: 〈0;f419〉 f421: 〈0;f420〉 f422: 〈0;f421〉 f423: 〈0;f422〉 f424: 〈0;f423〉 f425: 〈0;f424〉 f426: 〈0;f425〉 f427: 〈0;f426〉 f428: 〈0;f427〉 f429: 〈0;f428〉 f430: 〈0;f429〉 f431: 〈0;f430〉 f432: 〈0;f431〉 f433: 〈0;f432〉 f434: 〈0;f433〉 f435: 〈0;f434〉 f436: 〈0;f435〉 f437: 〈0;f436〉 f438: 〈0;f437〉 f439: 〈0;f438〉 f440: 〈0;f439〉 f441: 〈0;f440〉 f442: 〈0;f441〉 f443: 〈0;f442〉 f444: 〈0;f443〉 f445: 〈0;f444〉 f446: 〈0;f445〉 f447: 〈0;f446〉 f448: 〈0;f447〉 f449: 〈0;f448〉 f450: 〈0;f449〉 f451: 〈0;f450〉 f452: 〈0;f451〉 f453: 〈0;f452〉 f454: 〈0;f453〉 f455: 〈0;f454〉 f456: 〈0;f455〉 f457: 〈0;f456〉 f458: 〈0;f457〉 f459: 〈0;f458〉 f460: 〈0;f459〉 f461: 〈0;f460〉 f462: 〈0;f461〉 f463: 〈0;f462〉 f464: 〈0;f463〉 f465: 〈0;f464〉 f466: 〈0;f465〉 f467: 〈0;f466〉 f468: 〈0;f467〉 f469: 〈0;f468〉 f470: 〈0;f469〉 f471: 〈0;f470〉 f472: 〈0;f471〉 f473: 〈0;f472〉 f474: 〈0;f473〉 f475: 〈0;f474〉 f476: 〈0;f475〉 f477: 〈0;f476〉 f478: 〈0;f477〉 f479: 〈0;f478〉 f480: 〈0;f479〉 f481: 〈0;f480〉 f482: 〈0;f481〉 f483: 〈0;f482〉 f484: 〈0;f483〉 f485: 〈0;f484〉 f486: 〈0;f485〉 f487: 〈0;f486〉 f488: 〈0;f487〉 f489: 〈0;f488〉 f490: 〈0;f489〉 f491: 〈0;f490〉 f492: 〈0;f491〉 f493: 〈0;f492〉 f494: 〈0;f493〉 f495: 〈0;f494〉 f496: 〈0;f495〉 f497: 〈0;f496〉 f498: 〈0;f497〉 f499: 〈0;f498〉 f500: 〈0;f499〉 f501: 〈0;f500〉 f502: 〈0;f501〉 f503: 〈0;f502〉 f504: 〈0;f503〉 f505: 〈0;f504〉 f506: 〈0;f505〉 f507: 〈0;f506〉 f508: 〈0;f507〉 f509: 〈0;f508〉 f510: 〈0;f509〉 f511: 〈0;f510〉 f512: 〈0;f511〉 f513: 〈0;f512〉 f514: 〈0;f513〉 f515: 〈0;f514〉 f516: 〈0;f515〉 f517: 〈0;f516〉 f518: 〈0;f517〉 f519: 〈0;f518〉 f520: 〈0;f519〉 f521: 〈0;f520〉 f522: 〈0;f521〉 f523: 〈0;f522〉 f524: 〈0;f523〉 f525: 〈0;f524〉 f526: 〈0;f525〉 f527: 〈0;f526〉 f528: 〈0;f527〉 f529: 〈0;f528〉 f530: 〈0;f529〉 f531: 〈0;f530〉 f532: 〈0;f531〉 f533: 〈0;f532〉 f534: 〈0;f533〉 f535: 〈0;f534〉 f536: 〈0;f535〉 f537: 〈0;f536〉 f538: 〈0;f537〉 f539: 〈0;f538〉 f540: 〈0;f539〉 f541: 〈0;f540〉 f542: 〈0;f541〉 f543: 〈0;f542〉 f544: 〈0;f543〉 f545: 〈0;f544〉 f546: 〈0;f545〉 f547: 〈0;f546〉 f548: 〈0;f547〉 f549: 〈0;f548〉 f550: 〈0;f549〉 f551: 〈0;f550〉 f552: 〈0;f551〉 f553: 〈0;f552〉 f554: 〈0;f553〉 f555: 〈0;f554〉 f556: 〈0;f555〉 f557: 〈0;f556〉 f558: 〈0;f557〉 f559: 〈0;f558〉 f560: 〈0;f559〉 f561: 〈0;f560〉 f562: 〈0;f561〉 f563: 〈0;f562〉 f564: 〈0;f563〉 f565: 〈0;f564〉 f566: 〈0;f565〉 f567: 〈0;f566〉 f568: 〈0;f567〉 f569: 〈0;f568〉 f570: 〈0;f569〉 f571: 〈0;f570〉 f572: 〈0;f571〉 f573: 〈0;f572〉 f574: 〈0;f573〉 f575: 〈0;f574〉 f576: 〈0;f575〉 f577: 〈0;f576〉 f578: 〈0;f577〉 f579: 〈0;f578〉 f580: 〈0;f579〉 f581: 〈0;f580〉 f582: 〈0;f581〉 f583: 〈0;f582〉 f584: 〈0;f583〉 f585: 〈0;f584〉 f586: 〈0;f585〉 f587: 〈0;f586〉 f588: 〈0;f587〉 f589: 〈0;f588〉 f590: 〈0;f589〉 f591: 〈0;f590〉 f592: 〈0;f591〉 f593: 〈0;f592〉 f594: 〈0;f593〉 f595: 〈0;f594〉 f596: 〈0;f595〉 f597: 〈0;f596〉 f598: 〈0;f597〉 f599: 〈0;f598〉 f600: 〈0;f599〉 f601: 〈0;f600〉 f602: 〈0;f601〉 f603: 〈0;f602〉 f604: 〈0;f603〉 f605: 〈0;f604〉 f606: 〈0;f605〉 f607: 〈0;f606〉 f608: 〈0;f607〉 f609: 〈0;f608〉 f610: 〈0;f609〉 f611: 〈0;f610〉 f612: 〈0;f611〉 f613: 〈0;f612〉 f614: 〈0;f613〉 f615: 〈0;f614〉 f616: 〈0;f615〉 f617: 〈0;f616〉 f618: 〈0;f617〉 f619: 〈0;f618〉 f620: 〈0;f619〉 f621: 〈0;f620〉 f622: 〈0;f621〉 f623: 〈0;f622〉 f624: 〈0;f623〉 f625: 〈0;f624〉 f626: 〈0;f625〉 f627: 〈0;f626〉 f628: 〈0;f627〉 f629: 〈0;f628〉 f630: 〈0;f629〉 f631: 〈0;f630〉 f632: 〈0;f631〉 f633: 〈0;f632〉 f634: 〈0;f633〉 f635: 〈0;f634〉 f636: 〈0;f635〉 f637: 〈0;f636〉 f638: 〈0;f637〉 f639: 〈0;f638〉 f640: 〈0;f639〉 f641: 〈0;f640〉 f642: 〈0;f641〉 f643: 〈0;f642〉 f644: 〈0;f643〉 f645: 〈0;f644〉 f646: 〈0;f645〉 f647: 〈0;f646〉 f648: 〈0;f647〉 f649: 〈0;f648〉 f650: 〈0;f649〉 f651: 〈0;f650〉 f652: 〈0;f651〉 f653: 〈0;f652〉 f654: 〈0;f653〉 f655: 〈0;f654〉 f656: 〈0;f655〉 f657: 〈0;f656〉 f658: 〈0;f657〉 f659: 〈0;f658〉 f660: 〈0;f659〉 f661: 〈0;f660〉 f662: 〈0;f661〉 f663: 〈0;f662〉 f664: 〈0;f663〉 f665: 〈0;f664〉 f666: 〈0;f665〉 f667: 〈0;f666〉 f668: 〈0;f667〉 f669: 〈0;f668〉 f670: 〈0;f669〉 f671: 〈0;f670〉 f672: 〈0;f671〉 f673: 〈0;f672〉 f674: 〈0;f673〉 f675: 〈0;f674〉 f676: 〈0;f675〉 f677: 〈0;f676〉 f678: 〈0;f677〉 f679: 〈0;f678〉 f680: 〈0;f679〉 f681: 〈0;f680〉 f682: 〈0;f681〉 f683: 〈0;f682〉 f684: 〈0;f683〉 f685: 〈0;f684〉 f686: 〈0;f685〉 f687: 〈0;f686〉 f688: 〈0;f687〉 f689: 〈0;f688〉 f690: 〈0;f689〉 f691: 〈0;f690〉 f692: 〈0;f691〉 f693: 〈0;f692〉 f694: 〈0;f693〉 f695: 〈0;f694〉 f696: 〈0;f695〉 f697: 〈0;f696〉 f698: 〈0;f697〉 f699: 〈0;f698〉 f700: 〈0;f699〉 f701: 〈0;f700〉 f702: 〈0;f701〉 f703: 〈0;f702〉 f704: 〈0;f703〉 f705: 〈0;f704〉 f706: 〈0;f705〉 f707: 〈0;f706〉 f708: 〈0;f707〉 f709: 〈0;f708〉 f710: 〈0;f709〉 f711: 〈0;f710〉 f712: 〈0;f711〉 f713: 〈0;f712〉 f714: 〈0;f713〉 f715: 〈0;f714〉 f716: 〈0;f715〉 f717: 〈0;f716〉 f718: 〈0;f717〉 f719: 〈0;f718〉 f720: 〈0;f719〉 f721: 〈0;f720〉 f722: 〈0;f721〉 f723: 〈0;f722〉 f724: 〈0;f723〉 f725: 〈0;f724〉 f726: 〈0;f725〉 f727: 〈0;f726〉 f728: 〈0;f727〉 f729: 〈0;f728〉 f730: 〈0;f729〉 f731: 〈0;f730〉 f732: 〈0;f731〉 f733: 〈0;f732〉 f734: 〈0;f733〉 f735: 〈0;f734〉 f736: 〈0;f735〉 f737: 〈0;f736〉 f738: 〈0;f737〉 f739: 〈0;f738〉 f740: 〈0;f739〉 f741: 〈0;f740〉 f742: 〈0;f741〉 f743: 〈0;f742〉 f744: 〈0;f743〉 f745: 〈0;f744〉 f746: 〈0;f745〉 f747: 〈0;f746〉 f748: 〈0;f747〉 f749: 〈0;f748〉 f750: 〈0;f749〉 f751: 〈0;f750〉 f752: 〈0;f751〉 f753: 〈0;f752〉 f754: 〈0;f753〉 f755: 〈0;f754〉 f756: 〈0;f755〉 f757: 〈0;f756〉 f758: 〈0;f757〉 f759: 〈0;f758〉 f760: 〈0;f759〉 f761: 〈0;f760〉 f762: 〈0;f761〉 f763: 〈0;f762〉 f764: 〈0;f763〉 f765: 〈0;f764〉 f766: 〈0;f765〉 f767: 〈0;f766〉 f768: 〈0;f767〉 f769: 〈0;f768〉 f770: 〈0;f769〉 f771: 〈0;f770〉 f772: 〈0;f771〉 f773: 〈0;f772〉 f774: 〈0;f773〉 f775: 〈0;f774〉 f776: 〈0;f775〉 f777: 〈0;f776〉 f778: 〈0;f777〉 f779: 〈0;f778〉 f780: 〈0;f779〉 f781: 〈0;f780〉 f782: 〈0;f781〉 f783: 〈0;f782〉 f784: 〈0;f783〉 f785: 〈0;f784〉 f786: 〈0;f785〉 f787: 〈0;f786〉 f788: 〈0;f787〉 f789: 〈0;f788〉 f790: 〈0;f789〉 f791: 〈0;f790〉 f792: 〈0;f791〉 f793: 〈0;f792〉 f794: 〈0;f793〉 f795: 〈0;f794〉 f796: 〈0;f795〉 f797: 〈0;f796〉 f798: 〈0;f797〉 f799: 〈0;f798〉 f800: 〈0;f799〉 f801: 〈0;f800〉 f802: 〈0;f801〉 f803: 〈0;f802〉 f804: 〈0;f803〉 f805: 〈0;f804〉 f806: 〈0;f805〉 f807: 〈0;f806〉 f808: 〈0;f807〉 f809: 〈0;f808〉 f810: 〈0;f809〉 f811: 〈0;f810〉 f812: 〈0;f811〉 f813: 〈0;f812〉 f814: 〈0;f813〉 f815: 〈0;f814〉 f816: 〈0;f815〉 f817: 〈0;f816〉 f818: 〈0;f817〉 f819: 〈0;f818〉 f820: 〈0;f819〉 f821: 〈0;f820〉 f822: 〈0;f821〉 f823: 〈0;f822〉 f824: 〈0;f823〉 f825: 〈0;f824〉 f826: 〈0;f825〉 f827: 〈0;f826〉 f828: 〈0;f827〉 f829: 〈0;f828〉 f830: 〈0;f829〉 f831: 〈0;f830〉 f832: 〈0;f831〉 f833: 〈0;f832〉 f834: 〈0;f833〉 f835: 〈0;f834〉 f836: 〈0;f835〉 f837: 〈0;f836〉 f838: 〈0;f837〉 f839: 〈0;f838〉 f840: 〈0;f839〉 f841: 〈0;f840〉 f842: 〈0;f841〉 f843: 〈0;f842〉 f844: 〈0;f843〉 f845: 〈0;f844〉 f846: 〈0;f845〉 f847: 〈0;f846〉 f848: 〈0;f847〉 f849: 〈0;f848〉 f850: 〈0;f849〉 f851: 〈0;f850〉 f852: 〈0;f851〉 f853: 〈0;f852〉 f854: 〈0;f853〉 f855: 〈0;f854〉 f856: 〈0;f855〉 f857: 〈0;f856〉 f858: 〈0;f857〉 f859: 〈0;f858〉 f860: 〈0;f859〉 f861: 〈0;f860〉 f862: 〈0;f861〉 f863: 〈0;f862〉 f864: 〈0;f863〉 f865: 〈0;f864〉 f866: 〈0;f865〉 f867: 〈0;f866〉 f868: 〈0;f867〉 f869: 〈0;f868〉 f870: 〈0;f869〉 f871: 〈0;f870〉 f872: 〈0;f871〉 f873: 〈0;f872〉 f874: 〈0;f873〉 f875: 〈0;f874〉 f876: 〈0;f875〉 f877: 〈0;f876〉 f878: 〈0;f877〉 f879: 〈0;f878〉 f880: 〈0;f879〉 f881: 〈0;f880〉 f882: 〈0;f881〉 f883: 〈0;f882〉 f884: 〈0;f883〉 f885: 〈0;f884〉 f886: 〈0;f885〉 f887: 〈0;f886〉 f888: 〈0;f887〉 f889: 〈0;f888〉 f890: 〈0;f889〉 f891: 〈0;f890〉 f892: 〈0;f891〉 f893: 〈0;f892〉 f894: 〈0;f893〉 f895: 〈0;f894〉 f896: 〈0;f895〉 f897: 〈0;f896〉 f898: 〈0;f897〉 f899: 〈0;f898〉 f900: 〈0;f899〉 f901: 〈0;f900〉 f902: 〈0;f901〉 f903: 〈0;f902〉 f904: 〈0;f903〉 f905: 〈0;f904〉 f906: 〈0;f905〉 f907: 〈0;f906〉 f908: 〈0;f907〉 f909: 〈0;f908〉 f910: 〈0;f909〉 f911: 〈0;f910〉 f912: 〈0;f911〉 f913: 〈0;f912〉 f914: 〈0;f913〉 f915: 〈0;f914〉 f916: 〈0;f915〉 f917: 〈0;f916〉 f918: 〈0;f917〉 f919: 〈0;f918〉 f920: 〈0;f919〉 f921: 〈0;f920〉 f922: 〈0;f921〉 f923: 〈0;f922〉 f924: 〈0;f923〉 f925: 〈0;f924〉 f926: 〈0;f925〉 f927: 〈0;f926〉 f928: 〈0;f927〉 f929: 〈0;f928〉 f930: 〈0;f929〉 f931: 〈0;f930〉 f932: 〈0;f931〉 f933: 〈0;f932〉 f934: 〈0;f933〉 f935: 〈0;f934〉 f936: 〈0;f935〉 f937: 〈0;f936〉 f938: 〈0;f937〉 f939: 〈0;f938〉 f940: 〈0;f939〉 f941: 〈0;f940〉 f942: 〈0;f941〉 f943: 〈0;f942〉 f944: 〈0;f943〉 f945: 〈0;f944〉 f946: 〈0;f945〉 f947: 〈0;f946〉 f948: 〈0;f947〉 f949: 〈0;f948〉 f950: 〈0;f949〉 f951: 〈0;f950〉 f952: 〈0;f951〉 f953: 〈0;f952〉 f954: 〈0;f953〉 f955: 〈0;f954〉 f956: 〈0;f955〉 f957: 〈0;f956〉 f958: 〈0;f957〉 f959: 〈0;f958〉 f960: 〈0;f959〉 f961: 〈0;f960〉 f962: 〈0;f961〉 f963: 〈0;f962〉 f964: 〈0;f963〉 f965: 〈0;f964〉 f966: 〈0;f965〉 f967: 〈0;f966〉 f968: 〈0;f967〉 f969: 〈0;f968〉 f970: 〈0;f969〉 f971: 〈0;f970〉 f972: 〈0;f971〉 f973: 〈0;f972〉 f974: 〈0;f973〉 f975: 〈0;f974〉 f976: 〈0;f975〉 f977: 〈0;f976〉 f978: 〈0;f977〉 f979: 〈0;f978〉 f980: 〈0;f979〉 f981: 〈0;f980〉 f982: 〈0;f981〉 f983: 〈0;f982〉 f984: 〈0;f983〉 f985: 〈0;f984〉 f986: 〈0;f985〉 f987: 〈0;f986〉 f988: 〈0;f987〉 f989: 〈0;f988〉 f990: 〈0;f989〉 f991: 〈0;f990〉 f992: 〈0;f991〉 f993: 〈0;f992〉 f994: 〈0;f993〉 f995: 〈0;f994〉 f996: 〈0;f995〉 f997: 〈0;f996〉 f998: 〈0;f997〉 f999: 〈0;f998〉 f1000: 〈0;f999〉 } -- out/evalalpha/stats -- Leaks: 1001 Freed: 0 Reused: 0 Allocs: 1001 Retain: 0 Unifications: 1001 Conjuncts: 2001 Disjuncts: 0 -- out/eval -- (struct){ f1: (string){ string } f2: (string){ string } f3: (string){ string } f4: (string){ string } f5: (string){ string } f6: (string){ string } f7: (string){ string } f8: (string){ string } f9: (string){ string } f10: (string){ string } f11: (string){ string } f12: (string){ string } f13: (string){ string } f14: (string){ string } f15: (string){ string } f16: (string){ string } f17: (string){ string } f18: (string){ string } f19: (string){ string } f20: (string){ string } f21: (string){ string } f22: (string){ string } f23: (string){ string } f24: (string){ string } f25: (string){ string } f26: (string){ string } f27: (string){ string } f28: (string){ string } f29: (string){ string } f30: (string){ string } f31: (string){ string } f32: (string){ string } f33: (string){ string } f34: (string){ string } f35: (string){ string } f36: (string){ string } f37: (string){ string } f38: (string){ string } f39: (string){ string } f40: (string){ string } f41: (string){ string } f42: (string){ string } f43: (string){ string } f44: (string){ string } f45: (string){ string } f46: (string){ string } f47: (string){ string } f48: (string){ string } f49: (string){ string } f50: (string){ string } f51: (string){ string } f52: (string){ string } f53: (string){ string } f54: (string){ string } f55: (string){ string } f56: (string){ string } f57: (string){ string } f58: (string){ string } f59: (string){ string } f60: (string){ string } f61: (string){ string } f62: (string){ string } f63: (string){ string } f64: (string){ string } f65: (string){ string } f66: (string){ string } f67: (string){ string } f68: (string){ string } f69: (string){ string } f70: (string){ string } f71: (string){ string } f72: (string){ string } f73: (string){ string } f74: (string){ string } f75: (string){ string } f76: (string){ string } f77: (string){ string } f78: (string){ string } f79: (string){ string } f80: (string){ string } f81: (string){ string } f82: (string){ string } f83: (string){ string } f84: (string){ string } f85: (string){ string } f86: (string){ string } f87: (string){ string } f88: (string){ string } f89: (string){ string } f90: (string){ string } f91: (string){ string } f92: (string){ string } f93: (string){ string } f94: (string){ string } f95: (string){ string } f96: (string){ string } f97: (string){ string } f98: (string){ string } f99: (string){ string } f100: (string){ string } f101: (string){ string } f102: (string){ string } f103: (string){ string } f104: (string){ string } f105: (string){ string } f106: (string){ string } f107: (string){ string } f108: (string){ string } f109: (string){ string } f110: (string){ string } f111: (string){ string } f112: (string){ string } f113: (string){ string } f114: (string){ string } f115: (string){ string } f116: (string){ string } f117: (string){ string } f118: (string){ string } f119: (string){ string } f120: (string){ string } f121: (string){ string } f122: (string){ string } f123: (string){ string } f124: (string){ string } f125: (string){ string } f126: (string){ string } f127: (string){ string } f128: (string){ string } f129: (string){ string } f130: (string){ string } f131: (string){ string } f132: (string){ string } f133: (string){ string } f134: (string){ string } f135: (string){ string } f136: (string){ string } f137: (string){ string } f138: (string){ string } f139: (string){ string } f140: (string){ string } f141: (string){ string } f142: (string){ string } f143: (string){ string } f144: (string){ string } f145: (string){ string } f146: (string){ string } f147: (string){ string } f148: (string){ string } f149: (string){ string } f150: (string){ string } f151: (string){ string } f152: (string){ string } f153: (string){ string } f154: (string){ string } f155: (string){ string } f156: (string){ string } f157: (string){ string } f158: (string){ string } f159: (string){ string } f160: (string){ string } f161: (string){ string } f162: (string){ string } f163: (string){ string } f164: (string){ string } f165: (string){ string } f166: (string){ string } f167: (string){ string } f168: (string){ string } f169: (string){ string } f170: (string){ string } f171: (string){ string } f172: (string){ string } f173: (string){ string } f174: (string){ string } f175: (string){ string } f176: (string){ string } f177: (string){ string } f178: (string){ string } f179: (string){ string } f180: (string){ string } f181: (string){ string } f182: (string){ string } f183: (string){ string } f184: (string){ string } f185: (string){ string } f186: (string){ string } f187: (string){ string } f188: (string){ string } f189: (string){ string } f190: (string){ string } f191: (string){ string } f192: (string){ string } f193: (string){ string } f194: (string){ string } f195: (string){ string } f196: (string){ string } f197: (string){ string } f198: (string){ string } f199: (string){ string } f200: (string){ string } f201: (string){ string } f202: (string){ string } f203: (string){ string } f204: (string){ string } f205: (string){ string } f206: (string){ string } f207: (string){ string } f208: (string){ string } f209: (string){ string } f210: (string){ string } f211: (string){ string } f212: (string){ string } f213: (string){ string } f214: (string){ string } f215: (string){ string } f216: (string){ string } f217: (string){ string } f218: (string){ string } f219: (string){ string } f220: (string){ string } f221: (string){ string } f222: (string){ string } f223: (string){ string } f224: (string){ string } f225: (string){ string } f226: (string){ string } f227: (string){ string } f228: (string){ string } f229: (string){ string } f230: (string){ string } f231: (string){ string } f232: (string){ string } f233: (string){ string } f234: (string){ string } f235: (string){ string } f236: (string){ string } f237: (string){ string } f238: (string){ string } f239: (string){ string } f240: (string){ string } f241: (string){ string } f242: (string){ string } f243: (string){ string } f244: (string){ string } f245: (string){ string } f246: (string){ string } f247: (string){ string } f248: (string){ string } f249: (string){ string } f250: (string){ string } f251: (string){ string } f252: (string){ string } f253: (string){ string } f254: (string){ string } f255: (string){ string } f256: (string){ string } f257: (string){ string } f258: (string){ string } f259: (string){ string } f260: (string){ string } f261: (string){ string } f262: (string){ string } f263: (string){ string } f264: (string){ string } f265: (string){ string } f266: (string){ string } f267: (string){ string } f268: (string){ string } f269: (string){ string } f270: (string){ string } f271: (string){ string } f272: (string){ string } f273: (string){ string } f274: (string){ string } f275: (string){ string } f276: (string){ string } f277: (string){ string } f278: (string){ string } f279: (string){ string } f280: (string){ string } f281: (string){ string } f282: (string){ string } f283: (string){ string } f284: (string){ string } f285: (string){ string } f286: (string){ string } f287: (string){ string } f288: (string){ string } f289: (string){ string } f290: (string){ string } f291: (string){ string } f292: (string){ string } f293: (string){ string } f294: (string){ string } f295: (string){ string } f296: (string){ string } f297: (string){ string } f298: (string){ string } f299: (string){ string } f300: (string){ string } f301: (string){ string } f302: (string){ string } f303: (string){ string } f304: (string){ string } f305: (string){ string } f306: (string){ string } f307: (string){ string } f308: (string){ string } f309: (string){ string } f310: (string){ string } f311: (string){ string } f312: (string){ string } f313: (string){ string } f314: (string){ string } f315: (string){ string } f316: (string){ string } f317: (string){ string } f318: (string){ string } f319: (string){ string } f320: (string){ string } f321: (string){ string } f322: (string){ string } f323: (string){ string } f324: (string){ string } f325: (string){ string } f326: (string){ string } f327: (string){ string } f328: (string){ string } f329: (string){ string } f330: (string){ string } f331: (string){ string } f332: (string){ string } f333: (string){ string } f334: (string){ string } f335: (string){ string } f336: (string){ string } f337: (string){ string } f338: (string){ string } f339: (string){ string } f340: (string){ string } f341: (string){ string } f342: (string){ string } f343: (string){ string } f344: (string){ string } f345: (string){ string } f346: (string){ string } f347: (string){ string } f348: (string){ string } f349: (string){ string } f350: (string){ string } f351: (string){ string } f352: (string){ string } f353: (string){ string } f354: (string){ string } f355: (string){ string } f356: (string){ string } f357: (string){ string } f358: (string){ string } f359: (string){ string } f360: (string){ string } f361: (string){ string } f362: (string){ string } f363: (string){ string } f364: (string){ string } f365: (string){ string } f366: (string){ string } f367: (string){ string } f368: (string){ string } f369: (string){ string } f370: (string){ string } f371: (string){ string } f372: (string){ string } f373: (string){ string } f374: (string){ string } f375: (string){ string } f376: (string){ string } f377: (string){ string } f378: (string){ string } f379: (string){ string } f380: (string){ string } f381: (string){ string } f382: (string){ string } f383: (string){ string } f384: (string){ string } f385: (string){ string } f386: (string){ string } f387: (string){ string } f388: (string){ string } f389: (string){ string } f390: (string){ string } f391: (string){ string } f392: (string){ string } f393: (string){ string } f394: (string){ string } f395: (string){ string } f396: (string){ string } f397: (string){ string } f398: (string){ string } f399: (string){ string } f400: (string){ string } f401: (string){ string } f402: (string){ string } f403: (string){ string } f404: (string){ string } f405: (string){ string } f406: (string){ string } f407: (string){ string } f408: (string){ string } f409: (string){ string } f410: (string){ string } f411: (string){ string } f412: (string){ string } f413: (string){ string } f414: (string){ string } f415: (string){ string } f416: (string){ string } f417: (string){ string } f418: (string){ string } f419: (string){ string } f420: (string){ string } f421: (string){ string } f422: (string){ string } f423: (string){ string } f424: (string){ string } f425: (string){ string } f426: (string){ string } f427: (string){ string } f428: (string){ string } f429: (string){ string } f430: (string){ string } f431: (string){ string } f432: (string){ string } f433: (string){ string } f434: (string){ string } f435: (string){ string } f436: (string){ string } f437: (string){ string } f438: (string){ string } f439: (string){ string } f440: (string){ string } f441: (string){ string } f442: (string){ string } f443: (string){ string } f444: (string){ string } f445: (string){ string } f446: (string){ string } f447: (string){ string } f448: (string){ string } f449: (string){ string } f450: (string){ string } f451: (string){ string } f452: (string){ string } f453: (string){ string } f454: (string){ string } f455: (string){ string } f456: (string){ string } f457: (string){ string } f458: (string){ string } f459: (string){ string } f460: (string){ string } f461: (string){ string } f462: (string){ string } f463: (string){ string } f464: (string){ string } f465: (string){ string } f466: (string){ string } f467: (string){ string } f468: (string){ string } f469: (string){ string } f470: (string){ string } f471: (string){ string } f472: (string){ string } f473: (string){ string } f474: (string){ string } f475: (string){ string } f476: (string){ string } f477: (string){ string } f478: (string){ string } f479: (string){ string } f480: (string){ string } f481: (string){ string } f482: (string){ string } f483: (string){ string } f484: (string){ string } f485: (string){ string } f486: (string){ string } f487: (string){ string } f488: (string){ string } f489: (string){ string } f490: (string){ string } f491: (string){ string } f492: (string){ string } f493: (string){ string } f494: (string){ string } f495: (string){ string } f496: (string){ string } f497: (string){ string } f498: (string){ string } f499: (string){ string } f500: (string){ string } f501: (string){ string } f502: (string){ string } f503: (string){ string } f504: (string){ string } f505: (string){ string } f506: (string){ string } f507: (string){ string } f508: (string){ string } f509: (string){ string } f510: (string){ string } f511: (string){ string } f512: (string){ string } f513: (string){ string } f514: (string){ string } f515: (string){ string } f516: (string){ string } f517: (string){ string } f518: (string){ string } f519: (string){ string } f520: (string){ string } f521: (string){ string } f522: (string){ string } f523: (string){ string } f524: (string){ string } f525: (string){ string } f526: (string){ string } f527: (string){ string } f528: (string){ string } f529: (string){ string } f530: (string){ string } f531: (string){ string } f532: (string){ string } f533: (string){ string } f534: (string){ string } f535: (string){ string } f536: (string){ string } f537: (string){ string } f538: (string){ string } f539: (string){ string } f540: (string){ string } f541: (string){ string } f542: (string){ string } f543: (string){ string } f544: (string){ string } f545: (string){ string } f546: (string){ string } f547: (string){ string } f548: (string){ string } f549: (string){ string } f550: (string){ string } f551: (string){ string } f552: (string){ string } f553: (string){ string } f554: (string){ string } f555: (string){ string } f556: (string){ string } f557: (string){ string } f558: (string){ string } f559: (string){ string } f560: (string){ string } f561: (string){ string } f562: (string){ string } f563: (string){ string } f564: (string){ string } f565: (string){ string } f566: (string){ string } f567: (string){ string } f568: (string){ string } f569: (string){ string } f570: (string){ string } f571: (string){ string } f572: (string){ string } f573: (string){ string } f574: (string){ string } f575: (string){ string } f576: (string){ string } f577: (string){ string } f578: (string){ string } f579: (string){ string } f580: (string){ string } f581: (string){ string } f582: (string){ string } f583: (string){ string } f584: (string){ string } f585: (string){ string } f586: (string){ string } f587: (string){ string } f588: (string){ string } f589: (string){ string } f590: (string){ string } f591: (string){ string } f592: (string){ string } f593: (string){ string } f594: (string){ string } f595: (string){ string } f596: (string){ string } f597: (string){ string } f598: (string){ string } f599: (string){ string } f600: (string){ string } f601: (string){ string } f602: (string){ string } f603: (string){ string } f604: (string){ string } f605: (string){ string } f606: (string){ string } f607: (string){ string } f608: (string){ string } f609: (string){ string } f610: (string){ string } f611: (string){ string } f612: (string){ string } f613: (string){ string } f614: (string){ string } f615: (string){ string } f616: (string){ string } f617: (string){ string } f618: (string){ string } f619: (string){ string } f620: (string){ string } f621: (string){ string } f622: (string){ string } f623: (string){ string } f624: (string){ string } f625: (string){ string } f626: (string){ string } f627: (string){ string } f628: (string){ string } f629: (string){ string } f630: (string){ string } f631: (string){ string } f632: (string){ string } f633: (string){ string } f634: (string){ string } f635: (string){ string } f636: (string){ string } f637: (string){ string } f638: (string){ string } f639: (string){ string } f640: (string){ string } f641: (string){ string } f642: (string){ string } f643: (string){ string } f644: (string){ string } f645: (string){ string } f646: (string){ string } f647: (string){ string } f648: (string){ string } f649: (string){ string } f650: (string){ string } f651: (string){ string } f652: (string){ string } f653: (string){ string } f654: (string){ string } f655: (string){ string } f656: (string){ string } f657: (string){ string } f658: (string){ string } f659: (string){ string } f660: (string){ string } f661: (string){ string } f662: (string){ string } f663: (string){ string } f664: (string){ string } f665: (string){ string } f666: (string){ string } f667: (string){ string } f668: (string){ string } f669: (string){ string } f670: (string){ string } f671: (string){ string } f672: (string){ string } f673: (string){ string } f674: (string){ string } f675: (string){ string } f676: (string){ string } f677: (string){ string } f678: (string){ string } f679: (string){ string } f680: (string){ string } f681: (string){ string } f682: (string){ string } f683: (string){ string } f684: (string){ string } f685: (string){ string } f686: (string){ string } f687: (string){ string } f688: (string){ string } f689: (string){ string } f690: (string){ string } f691: (string){ string } f692: (string){ string } f693: (string){ string } f694: (string){ string } f695: (string){ string } f696: (string){ string } f697: (string){ string } f698: (string){ string } f699: (string){ string } f700: (string){ string } f701: (string){ string } f702: (string){ string } f703: (string){ string } f704: (string){ string } f705: (string){ string } f706: (string){ string } f707: (string){ string } f708: (string){ string } f709: (string){ string } f710: (string){ string } f711: (string){ string } f712: (string){ string } f713: (string){ string } f714: (string){ string } f715: (string){ string } f716: (string){ string } f717: (string){ string } f718: (string){ string } f719: (string){ string } f720: (string){ string } f721: (string){ string } f722: (string){ string } f723: (string){ string } f724: (string){ string } f725: (string){ string } f726: (string){ string } f727: (string){ string } f728: (string){ string } f729: (string){ string } f730: (string){ string } f731: (string){ string } f732: (string){ string } f733: (string){ string } f734: (string){ string } f735: (string){ string } f736: (string){ string } f737: (string){ string } f738: (string){ string } f739: (string){ string } f740: (string){ string } f741: (string){ string } f742: (string){ string } f743: (string){ string } f744: (string){ string } f745: (string){ string } f746: (string){ string } f747: (string){ string } f748: (string){ string } f749: (string){ string } f750: (string){ string } f751: (string){ string } f752: (string){ string } f753: (string){ string } f754: (string){ string } f755: (string){ string } f756: (string){ string } f757: (string){ string } f758: (string){ string } f759: (string){ string } f760: (string){ string } f761: (string){ string } f762: (string){ string } f763: (string){ string } f764: (string){ string } f765: (string){ string } f766: (string){ string } f767: (string){ string } f768: (string){ string } f769: (string){ string } f770: (string){ string } f771: (string){ string } f772: (string){ string } f773: (string){ string } f774: (string){ string } f775: (string){ string } f776: (string){ string } f777: (string){ string } f778: (string){ string } f779: (string){ string } f780: (string){ string } f781: (string){ string } f782: (string){ string } f783: (string){ string } f784: (string){ string } f785: (string){ string } f786: (string){ string } f787: (string){ string } f788: (string){ string } f789: (string){ string } f790: (string){ string } f791: (string){ string } f792: (string){ string } f793: (string){ string } f794: (string){ string } f795: (string){ string } f796: (string){ string } f797: (string){ string } f798: (string){ string } f799: (string){ string } f800: (string){ string } f801: (string){ string } f802: (string){ string } f803: (string){ string } f804: (string){ string } f805: (string){ string } f806: (string){ string } f807: (string){ string } f808: (string){ string } f809: (string){ string } f810: (string){ string } f811: (string){ string } f812: (string){ string } f813: (string){ string } f814: (string){ string } f815: (string){ string } f816: (string){ string } f817: (string){ string } f818: (string){ string } f819: (string){ string } f820: (string){ string } f821: (string){ string } f822: (string){ string } f823: (string){ string } f824: (string){ string } f825: (string){ string } f826: (string){ string } f827: (string){ string } f828: (string){ string } f829: (string){ string } f830: (string){ string } f831: (string){ string } f832: (string){ string } f833: (string){ string } f834: (string){ string } f835: (string){ string } f836: (string){ string } f837: (string){ string } f838: (string){ string } f839: (string){ string } f840: (string){ string } f841: (string){ string } f842: (string){ string } f843: (string){ string } f844: (string){ string } f845: (string){ string } f846: (string){ string } f847: (string){ string } f848: (string){ string } f849: (string){ string } f850: (string){ string } f851: (string){ string } f852: (string){ string } f853: (string){ string } f854: (string){ string } f855: (string){ string } f856: (string){ string } f857: (string){ string } f858: (string){ string } f859: (string){ string } f860: (string){ string } f861: (string){ string } f862: (string){ string } f863: (string){ string } f864: (string){ string } f865: (string){ string } f866: (string){ string } f867: (string){ string } f868: (string){ string } f869: (string){ string } f870: (string){ string } f871: (string){ string } f872: (string){ string } f873: (string){ string } f874: (string){ string } f875: (string){ string } f876: (string){ string } f877: (string){ string } f878: (string){ string } f879: (string){ string } f880: (string){ string } f881: (string){ string } f882: (string){ string } f883: (string){ string } f884: (string){ string } f885: (string){ string } f886: (string){ string } f887: (string){ string } f888: (string){ string } f889: (string){ string } f890: (string){ string } f891: (string){ string } f892: (string){ string } f893: (string){ string } f894: (string){ string } f895: (string){ string } f896: (string){ string } f897: (string){ string } f898: (string){ string } f899: (string){ string } f900: (string){ string } f901: (string){ string } f902: (string){ string } f903: (string){ string } f904: (string){ string } f905: (string){ string } f906: (string){ string } f907: (string){ string } f908: (string){ string } f909: (string){ string } f910: (string){ string } f911: (string){ string } f912: (string){ string } f913: (string){ string } f914: (string){ string } f915: (string){ string } f916: (string){ string } f917: (string){ string } f918: (string){ string } f919: (string){ string } f920: (string){ string } f921: (string){ string } f922: (string){ string } f923: (string){ string } f924: (string){ string } f925: (string){ string } f926: (string){ string } f927: (string){ string } f928: (string){ string } f929: (string){ string } f930: (string){ string } f931: (string){ string } f932: (string){ string } f933: (string){ string } f934: (string){ string } f935: (string){ string } f936: (string){ string } f937: (string){ string } f938: (string){ string } f939: (string){ string } f940: (string){ string } f941: (string){ string } f942: (string){ string } f943: (string){ string } f944: (string){ string } f945: (string){ string } f946: (string){ string } f947: (string){ string } f948: (string){ string } f949: (string){ string } f950: (string){ string } f951: (string){ string } f952: (string){ string } f953: (string){ string } f954: (string){ string } f955: (string){ string } f956: (string){ string } f957: (string){ string } f958: (string){ string } f959: (string){ string } f960: (string){ string } f961: (string){ string } f962: (string){ string } f963: (string){ string } f964: (string){ string } f965: (string){ string } f966: (string){ string } f967: (string){ string } f968: (string){ string } f969: (string){ string } f970: (string){ string } f971: (string){ string } f972: (string){ string } f973: (string){ string } f974: (string){ string } f975: (string){ string } f976: (string){ string } f977: (string){ string } f978: (string){ string } f979: (string){ string } f980: (string){ string } f981: (string){ string } f982: (string){ string } f983: (string){ string } f984: (string){ string } f985: (string){ string } f986: (string){ string } f987: (string){ string } f988: (string){ string } f989: (string){ string } f990: (string){ string } f991: (string){ string } f992: (string){ string } f993: (string){ string } f994: (string){ string } f995: (string){ string } f996: (string){ string } f997: (string){ string } f998: (string){ string } f999: (string){ string } f1000: (string){ string } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 1001 -Reused: 999 -Allocs: 2 +Leaks: 1001 +Freed: 0 +Reused: 0 +Allocs: 1001 Retain: 0 Unifications: 1001 -Conjuncts: 500501 -Disjuncts: 1001 +Conjuncts: 2001 +Disjuncts: 0 -- out/eval/stats -- Leaks: 0 Freed: 1001 Reused: 999 Allocs: 2 Retain: 0 Unifications: 1001 Conjuncts: 500501 Disjuncts: 1001 cue-lang-cue-db9cc73/cue/testdata/benchmarks/cycle.txtar000066400000000000000000000036631474664451600233750ustar00rootroot00000000000000-- stats.txt -- Leaks: 0 Freed: 25 Reused: 15 Allocs: 10 Retain: 1 Unifications: 15 Conjuncts: 30 Disjuncts: 26 -- in.cue -- sameValues: SmustBeF: { T: string | F F: x: T S: F } sameValues: CmustBeA: { A: x: [ string | A ] C: A } -- out/compile -- --- in.cue { sameValues: { SmustBeF: { T: (string|〈0;F〉) F: { x: 〈1;T〉 } S: 〈0;F〉 } } sameValues: { CmustBeA: { A: { x: [ (string|〈2;A〉), ] } C: 〈0;A〉 } } } -- out/eval/stats -- Leaks: 0 Freed: 25 Reused: 15 Allocs: 10 Retain: 1 Unifications: 15 Conjuncts: 30 Disjuncts: 26 -- out/evalalpha -- (struct){ sameValues: (struct){ SmustBeF: (struct){ T: (string){ string } F: (struct){ x: (string){ string } } S: ~(sameValues.SmustBeF.F) } CmustBeA: (struct){ A: (struct){ x: (#list){ 0: (string){ string } } } C: ~(sameValues.CmustBeA.A) } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -5,9 +5,7 @@ F: (struct){ x: (string){ string } } - S: (struct){ - x: (string){ string } - } + S: ~(sameValues.SmustBeF.F) } CmustBeA: (struct){ A: (struct){ @@ -15,11 +13,7 @@ 0: (string){ string } } } - C: (struct){ - x: (#list){ - 0: (string){ string } - } - } + C: ~(sameValues.CmustBeA.A) } } } -- out/eval -- (struct){ sameValues: (struct){ SmustBeF: (struct){ T: (string){ string } F: (struct){ x: (string){ string } } S: (struct){ x: (string){ string } } } CmustBeA: (struct){ A: (struct){ x: (#list){ 0: (string){ string } } } C: (struct){ x: (#list){ 0: (string){ string } } } } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/cycleshare.txtar000066400000000000000000002221071474664451600244140ustar00rootroot00000000000000-- in.cue -- // Test that cyclic references do not break structure sharing. This was the // underlying problem of Issue #3587. Note that this is not a problem related // to disjunctions. // These definitions represent a large tree of disjunctions. #D1: {a: #D2} | {b: #D2} | {c: #D2} #D2: {a: #D3} | {b: #D3} | {c: #D3} #D3: { one: {a: int} | {b: int} | {c: int} two: {a: string} | {b: string} | {c: string} three: {a: bool} | {b: bool} | {c: bool} } root: y: #D1 | [#D1] | {x: #D1} // Expensive path root: x: empty: {} root: "0": data: root_0.x.empty root: "1": data: root_1.x.empty root: "2": data: root_2.x.empty root: "3": data: root_3.x.empty // We want root to be shared in all of these cases. let root_0 = root let root_1 = root root_2: root root_3: root -- out/evalalpha/stats -- Leaks: 64 Freed: 0 Reused: 0 Allocs: 64 Retain: 0 Unifications: 43 Conjuncts: 175 Disjuncts: 21 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 8 -Freed: 965 -Reused: 951 -Allocs: 22 -Retain: 17 +Leaks: 64 +Freed: 0 +Reused: 0 +Allocs: 64 +Retain: 0 -Unifications: 559 -Conjuncts: 1046 -Disjuncts: 976 +Unifications: 43 +Conjuncts: 175 +Disjuncts: 21 -- out/eval/stats -- Leaks: 8 Freed: 965 Reused: 951 Allocs: 22 Retain: 17 Unifications: 559 Conjuncts: 1046 Disjuncts: 976 -- out/evalalpha -- (struct){ #D1: (#struct){ |((#struct){ a: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ b: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ c: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }) } #D2: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } #D3: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } root: (struct){ y: ((list|struct)){ |((#struct){ a: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ b: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ c: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#list){ 0: (#struct){ |((#struct){ a: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ b: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ c: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }) } }, (struct){ x: (#struct){ |((#struct){ a: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ b: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }, (#struct){ c: (#struct){ |((#struct){ a: ~(#D3) }, (#struct){ b: ~(#D3) }, (#struct){ c: ~(#D3) }) } }) } }) } x: (struct){ empty: (struct){ } } "0": (struct){ data: (struct){ } } "1": (struct){ data: (struct){ } } "2": (struct){ data: (struct){ } } "3": (struct){ data: (struct){ } } } let root_0#1 = ~(root) let root_1#2 = ~(root) root_2: ~(root) root_3: ~(root) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,305 +1,35 @@ -Errors: -root_2: structural cycle: - ./in.cue:19:18 - -Result: -(_|_){ - // [structural cycle] +(struct){ #D1: (#struct){ |((#struct){ a: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }, (#struct){ b: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }, (#struct){ c: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }) } #D2: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } #D3: (#struct){ one: (#struct){ |((#struct){ @@ -324,676 +54,81 @@ c: (bool){ bool } }) } } - root: (_|_){ - // [structural cycle] + root: (struct){ y: ((list|struct)){ |((#struct){ a: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }, (#struct){ b: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }, (#struct){ c: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }, (#list){ 0: (#struct){ |((#struct){ a: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }) } - }, (#struct){ - b: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }) } - }, (#struct){ - c: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) + }) } + }, (#struct){ + b: (#struct){ |((#struct){ + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) + }) } + }, (#struct){ + c: (#struct){ |((#struct){ + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }) } }, (struct){ x: (#struct){ |((#struct){ a: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }) } - }, (#struct){ - b: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }) } - }, (#struct){ - c: (#struct){ |((#struct){ - a: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - b: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } - }, (#struct){ - c: (#struct){ - one: (#struct){ |((#struct){ - a: (int){ int } - }, (#struct){ - b: (int){ int } - }, (#struct){ - c: (int){ int } - }) } - two: (#struct){ |((#struct){ - a: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - c: (string){ string } - }) } - three: (#struct){ |((#struct){ - a: (bool){ bool } - }, (#struct){ - b: (bool){ bool } - }, (#struct){ - c: (bool){ bool } - }) } - } + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) + }) } + }, (#struct){ + b: (#struct){ |((#struct){ + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) + }) } + }, (#struct){ + c: (#struct){ |((#struct){ + a: ~(#D3) + }, (#struct){ + b: ~(#D3) + }, (#struct){ + c: ~(#D3) }) } }) } }) } @@ -1009,34 +144,17 @@ data: (struct){ } } - "2": (_|_){ - // [structural cycle] - data: (_|_){ - // [structural cycle] root_2: structural cycle: - // ./in.cue:19:18 - } - } - "3": (_|_){ - // [structural cycle] - data: (_|_){ - // [structural cycle] root_2: structural cycle: - // ./in.cue:19:18 - } - } - } - let root_0#1 = (_|_){ - // [structural cycle] root_0: structural cycle: - // ./in.cue:17:18 - } - let root_1#2 = (_|_){ - // [structural cycle] root_1: structural cycle: - // ./in.cue:18:18 - } - root_2: (_|_){ - // [structural cycle] root_2: structural cycle: - // ./in.cue:19:18 - } - root_3: (_|_){ - // [structural cycle] - } + "2": (struct){ + data: (struct){ + } + } + "3": (struct){ + data: (struct){ + } + } + } + let root_0#1 = ~(root) + let root_1#2 = ~(root) + root_2: ~(root) + root_3: ~(root) } -- out/eval -- Errors: root_2: structural cycle: ./in.cue:19:18 Result: (_|_){ // [structural cycle] #D1: (#struct){ |((#struct){ a: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ b: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ c: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }) } #D2: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } #D3: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } root: (_|_){ // [structural cycle] y: ((list|struct)){ |((#struct){ a: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ b: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ c: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#list){ 0: (#struct){ |((#struct){ a: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ b: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ c: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }) } }, (struct){ x: (#struct){ |((#struct){ a: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ b: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }, (#struct){ c: (#struct){ |((#struct){ a: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ b: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }, (#struct){ c: (#struct){ one: (#struct){ |((#struct){ a: (int){ int } }, (#struct){ b: (int){ int } }, (#struct){ c: (int){ int } }) } two: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ c: (string){ string } }) } three: (#struct){ |((#struct){ a: (bool){ bool } }, (#struct){ b: (bool){ bool } }, (#struct){ c: (bool){ bool } }) } } }) } }) } }) } x: (struct){ empty: (struct){ } } "0": (struct){ data: (struct){ } } "1": (struct){ data: (struct){ } } "2": (_|_){ // [structural cycle] data: (_|_){ // [structural cycle] root_2: structural cycle: // ./in.cue:19:18 } } "3": (_|_){ // [structural cycle] data: (_|_){ // [structural cycle] root_2: structural cycle: // ./in.cue:19:18 } } } let root_0#1 = (_|_){ // [structural cycle] root_0: structural cycle: // ./in.cue:17:18 } let root_1#2 = (_|_){ // [structural cycle] root_1: structural cycle: // ./in.cue:18:18 } root_2: (_|_){ // [structural cycle] root_2: structural cycle: // ./in.cue:19:18 } root_3: (_|_){ // [structural cycle] } } -- out/compile -- --- in.cue { #D1: ({ a: 〈1;#D2〉 }|{ b: 〈1;#D2〉 }|{ c: 〈1;#D2〉 }) #D2: ({ a: 〈1;#D3〉 }|{ b: 〈1;#D3〉 }|{ c: 〈1;#D3〉 }) #D3: { one: ({ a: int }|{ b: int }|{ c: int }) two: ({ a: string }|{ b: string }|{ c: string }) three: ({ a: bool }|{ b: bool }|{ c: bool }) } root: { y: (〈1;#D1〉|[ 〈2;#D1〉, ]|{ x: 〈2;#D1〉 }) } root: { x: { empty: {} } } root: { "0": { data: 〈2;let root_0#1〉.x.empty } } root: { "1": { data: 〈2;let root_1#2〉.x.empty } } root: { "2": { data: 〈2;root_2〉.x.empty } } root: { "3": { data: 〈2;root_3〉.x.empty } } let root_0#1 = 〈0;root〉 let root_1#2 = 〈0;root〉 root_2: 〈0;root〉 root_3: 〈0;root〉 } cue-lang-cue-db9cc73/cue/testdata/benchmarks/decimal.txtar000066400000000000000000000016671474664451600236760ustar00rootroot00000000000000-- stats.txt -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 11 Disjuncts: 11 -- in.cue -- out: [ 123.45 + 987.65, 123.45 - 987.65, 123.45 * 987.65, 123.45 / 987.65, // whole integers 2 + 3, 7 - 1, 5 * 10, 20 / 4, 1 / 3, // fill all digits ] -- out/compile -- --- in.cue { out: [ (123.45 + 987.65), (123.45 - 987.65), (123.45 * 987.65), (123.45 / 987.65), (2 + 3), (7 - 1), (5 * 10), (20 / 4), (1 / 3), ] } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 11 Disjuncts: 11 -- out/eval -- (struct){ out: (#list){ 0: (float){ 1111.10 } 1: (float){ -864.20 } 2: (float){ 121925.3925 } 3: (float){ 0.1249936718473143320002025008859414 } 4: (int){ 5 } 5: (int){ 6 } 6: (int){ 50 } 7: (float){ 5.0 } 8: (float){ 0.3333333333333333333333333333333333 } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/deduparc.txtar000066400000000000000000000022331474664451600240550ustar00rootroot00000000000000-- stats.txt -- Leaks: 0 Freed: 11 Reused: 6 Allocs: 5 Retain: 0 Unifications: 7 Conjuncts: 29 Disjuncts: 11 -- in.cue -- package bench1 #Value: {type: "float"} | {type: "string"} foo: {type: "string"} foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value foo: #Value -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 6 Allocs: 5 Retain: 0 Unifications: 7 Conjuncts: 29 Disjuncts: 11 -- out/eval -- (struct){ #Value: (#struct){ |((#struct){ type: (string){ "float" } }, (#struct){ type: (string){ "string" } }) } foo: (#struct){ type: (string){ "string" } } } -- out/compile -- --- in.cue { #Value: ({ type: "float" }|{ type: "string" }) foo: { type: "string" } foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 foo: 〈0;#Value〉 } cue-lang-cue-db9cc73/cue/testdata/benchmarks/dedupelem.txtar000066400000000000000000000101441474664451600242320ustar00rootroot00000000000000-- stats.txt -- Leaks: 0 Freed: 16 Reused: 10 Allocs: 6 Retain: 0 Unifications: 10 Conjuncts: 94 Disjuncts: 16 -- in.cue -- package lpcorpus #Value: {type: "int"} | {type: "float"} | {type: "string"} foo: [{type: "float"}] & [...#Value] foo: [{type: "float"}] & [...#Value] foo: [{type: "float"}] & [...#Value] foo: [{type: "float"}] & [...#Value] foo: [{type: "float"}] & [...#Value] foo: [{type: "string"}] & [...#Value] foo: [{type: "string"}] & [...#Value] foo: [{type: "string"}] & [...#Value] foo: [{type: "float"}] & [...#Value] foo: [{type: "float"}] & [...#Value] -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 10 Allocs: 6 Retain: 0 Unifications: 10 Conjuncts: 94 Disjuncts: 16 -- out/evalalpha -- Errors: foo.0.type: conflicting values "string" and "float": ./in.cue:5:14 ./in.cue:10:14 Result: (_|_){ // [eval] #Value: (#struct){ |((#struct){ type: (string){ "int" } }, (#struct){ type: (string){ "float" } }, (#struct){ type: (string){ "string" } }) } foo: (_|_){ // [eval] 0: (_|_){ // [eval] type: (_|_){ // [eval] foo.0.type: conflicting values "string" and "float": // ./in.cue:5:14 // ./in.cue:10:14 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,10 +1,4 @@ Errors: -foo.0: 2 errors in empty disjunction: -foo.0.type: conflicting values "int" and "float": - ./in.cue:3:16 - ./in.cue:5:14 - ./in.cue:5:27 - ./in.cue:5:30 foo.0.type: conflicting values "string" and "float": ./in.cue:5:14 ./in.cue:10:14 @@ -22,15 +16,7 @@ foo: (_|_){ // [eval] 0: (_|_){ - // [eval] foo.0: 2 errors in empty disjunction: - // foo.0.type: conflicting values "int" and "float": - // ./in.cue:3:16 - // ./in.cue:5:14 - // ./in.cue:5:27 - // ./in.cue:5:30 - // foo.0.type: conflicting values "string" and "float": - // ./in.cue:5:14 - // ./in.cue:10:14 + // [eval] type: (_|_){ // [eval] foo.0.type: conflicting values "string" and "float": // ./in.cue:5:14 -- diff/explanation -- Improved and simplified error message which can be detected before disjunction. -- out/eval -- Errors: foo.0: 2 errors in empty disjunction: foo.0.type: conflicting values "int" and "float": ./in.cue:3:16 ./in.cue:5:14 ./in.cue:5:27 ./in.cue:5:30 foo.0.type: conflicting values "string" and "float": ./in.cue:5:14 ./in.cue:10:14 Result: (_|_){ // [eval] #Value: (#struct){ |((#struct){ type: (string){ "int" } }, (#struct){ type: (string){ "float" } }, (#struct){ type: (string){ "string" } }) } foo: (_|_){ // [eval] 0: (_|_){ // [eval] foo.0: 2 errors in empty disjunction: // foo.0.type: conflicting values "int" and "float": // ./in.cue:3:16 // ./in.cue:5:14 // ./in.cue:5:27 // ./in.cue:5:30 // foo.0.type: conflicting values "string" and "float": // ./in.cue:5:14 // ./in.cue:10:14 type: (_|_){ // [eval] foo.0.type: conflicting values "string" and "float": // ./in.cue:5:14 // ./in.cue:10:14 } } } } -- out/compile -- --- in.cue { #Value: ({ type: "int" }|{ type: "float" }|{ type: "string" }) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "string" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "string" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "string" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) foo: ([ { type: "float" }, ] & [ ...〈1;#Value〉, ]) } cue-lang-cue-db9cc73/cue/testdata/benchmarks/disjunctelim.txtar000066400000000000000000000101421474664451600247560ustar00rootroot00000000000000// TODO: make special benchmark test that tests repeated lines more accurately // and and automatically. -- in.cue -- // Should linearly increase with each repeated line. // automatically. pat: {[string]: 1} | {a: 2} // 9 conjuncts pat: {[string]: 1} | {a: 2} // 23 conjuncts (+14) pat: {[string]: 1} | {a: 2} // 34 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 45 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 56 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 67 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 78 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 89 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 100 conjuncts (+11) pat: {[string]: 1} | {a: 2} // 111 conjuncts (+11) // This also should grow linearly per repeated line. // Indicated list: [1] | [2] | [3] | [4] // 19 conjuncts; 4 disjuncts list: [1] | [2] | [3] | [4] // 52 conjuncts; 20 disjuncts (+33; +16) list: [1] | [2] | [3] | [4] // 85 conjuncts; 36 disjuncts (+33; +16) list: [1] | [2] | [3] | [4] // 118 conjuncts; 52 disjuncts (+33; +16) list: [1] | [2] | [3] | [4] // 151 conjuncts; 68 disjuncts (+33; +16) list: [1] | [2] | [3] | [4] // 184 conjuncts; 84 disjuncts (+33; +16) list: [1] | [2] | [3] | [4] // 217 conjuncts; 100 disjuncts (+33; +16) issue3610: { // Ensure disjuncts are disambiguated. The string field here is a reference // and causes a task to be added. Ensure that, for instance, disjuncts // >"b" and (>"b" & string) get equated when at least the task has // completed. #a #a: <"a" | >"b" | string #a: <"a" | >"b" | string // conjuncts 127 disjuncts 120 #a: <"a" | >"b" | string // conjuncts 219 disjuncts 210 (+92; +90) #a: <"a" | >"b" | string // conjuncts 311 disjuncts 300 (+92; +90) #a: <"a" | >"b" | string // conjuncts 403 disjuncts 390 (+92; +90) #a: <"a" | >"b" | string // conjuncts 495 disjuncts 480 (+92; +90) } -- out/evalalpha/stats -- Leaks: 612 Freed: 190 Reused: 190 Allocs: 612 Retain: 0 Unifications: 22 Conjuncts: 954 Disjuncts: 618 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 367 -Reused: 356 -Allocs: 11 +Leaks: 612 +Freed: 190 +Reused: 190 +Allocs: 612 Retain: 0 -Unifications: 133 -Conjuncts: 866 -Disjuncts: 367 +Unifications: 22 +Conjuncts: 954 +Disjuncts: 618 -- out/eval/stats -- Leaks: 0 Freed: 367 Reused: 356 Allocs: 11 Retain: 0 Unifications: 133 Conjuncts: 866 Disjuncts: 367 -- out/eval -- (struct){ pat: (struct){ |((struct){ }, (struct){ a: (int){ 2 } }) } list: (list){ |((#list){ 0: (int){ 1 } }, (#list){ 0: (int){ 2 } }, (#list){ 0: (int){ 3 } }, (#list){ 0: (int){ 4 } }) } issue3610: (string){ |((string){ <"a" #a: (string){ |((string){ <"a" }, (string){ >"b" }, (string){ string }) } }, (string){ >"b" #a: (string){ |((string){ <"a" }, (string){ >"b" }, (string){ string }) } }, (string){ string #a: (string){ |((string){ <"a" }, (string){ >"b" }, (string){ string }) } }) } } -- out/compile -- --- in.cue { pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) pat: ({ [string]: 1 }|{ a: 2 }) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) list: ([ 1, ]|[ 2, ]|[ 3, ]|[ 4, ]) issue3610: { 〈0;#a〉 #a: (<"a"|>"b"|string) #a: (<"a"|>"b"|string) #a: (<"a"|>"b"|string) #a: (<"a"|>"b"|string) #a: (<"a"|>"b"|string) #a: (<"a"|>"b"|string) } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/disjunction.txtar000066400000000000000000000044731474664451600246270ustar00rootroot00000000000000// Triggering recomputation of disjunctions on each branch results // in exponential run time. Ensure this does not happen. -- stats.txt -- Leaks: 0 Freed: 82 Reused: 74 Allocs: 8 Retain: 0 Unifications: 4 Conjuncts: 143 Disjuncts: 82 -- in.cue -- x: a0: {} x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: [_]: f: *1 | int x: a0: {} -- out/compile -- --- in.cue { x: { a0: {} } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { [_]: { f: (*1|int) } } x: { a0: {} } } -- out/evalalpha/stats -- Leaks: 162 Freed: 0 Reused: 0 Allocs: 162 Retain: 0 Unifications: 6 Conjuncts: 308 Disjuncts: 156 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 82 -Reused: 74 -Allocs: 8 +Leaks: 162 +Freed: 0 +Reused: 0 +Allocs: 162 Retain: 0 -Unifications: 4 -Conjuncts: 143 -Disjuncts: 82 +Unifications: 6 +Conjuncts: 308 +Disjuncts: 156 -- out/eval/stats -- Leaks: 0 Freed: 82 Reused: 74 Allocs: 8 Retain: 0 Unifications: 4 Conjuncts: 143 Disjuncts: 82 -- out/eval -- (struct){ x: (struct){ a0: (struct){ f: (int){ |(*(int){ 1 }, (int){ int }) } } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/inlinedisjunction.txtar000066400000000000000000000031501474664451600260150ustar00rootroot00000000000000-- in.cue -- #def: { {} | {c: string} {} | {c: string} {} | {c: string} {} | {c: string} {} | {c: string} {} | {c: string} {} | {c: string} {} | {c: string} {} | {c: string} {} | {a: string} } x: #def x: c: "foo" -- out/evalalpha/stats -- Leaks: 147 Freed: 2 Reused: 2 Allocs: 147 Retain: 0 Unifications: 17 Conjuncts: 218 Disjuncts: 76 -- out/eval -- (struct){ #def: (#struct){ |((#struct){ }, (#struct){ a: (string){ string } }, (#struct){ c: (string){ string } }, (#struct){ c: (string){ string } a: (string){ string } }) } x: (#struct){ |((#struct){ c: (string){ "foo" } }, (#struct){ c: (string){ "foo" } a: (string){ string } }) } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 4674 -Reused: 3903 -Allocs: 771 +Leaks: 147 +Freed: 2 +Reused: 2 +Allocs: 147 Retain: 0 -Unifications: 2590 -Conjuncts: 13409 -Disjuncts: 4674 +Unifications: 17 +Conjuncts: 218 +Disjuncts: 76 -- out/eval/stats -- Leaks: 0 Freed: 4674 Reused: 3903 Allocs: 771 Retain: 0 Unifications: 2590 Conjuncts: 13409 Disjuncts: 4674 -- out/compile -- --- in.cue { #def: { ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ c: string }) ({}|{ a: string }) } x: 〈0;#def〉 x: { c: "foo" } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/issue1684.txtar000066400000000000000000000173141474664451600237470ustar00rootroot00000000000000#Issue: 1684 // TODO: significantly reduce the number of counts in this evaluation. -- stats.txt -- Leaks: 0 Freed: 995025 Reused: 994976 Allocs: 49 Retain: 0 Unifications: 740771 Conjuncts: 3143640 Disjuncts: 995025 -- in.cue -- #Secret: { $secret: id: string } #secrets: #Secret | {[string]: #secrets} out: #secrets & { FOO: $secret: id: "100" ONE: TWO: THREE: $secret: id: "123" } #Secret: { $secret: _id: string } #secrets: #Secret | {[string]: #secrets} out: #secrets & { FOO: $secret: _id: "100" ONE: TWO: THREE: $secret: _id: "123" } -- perf.cue -- nestedCross: closed: { #D: {id: string} | {[string]: #D} #D: {id: string} | {[string]: #D} #D: {id: string} | {[string]: #D} } nestedCross: open: { D: {id: string} | {[string]: D} D: {id: string} | {[string]: D} D: {id: string} | {[string]: D} } // TODO(perf): support this case. This is currently highly exponential. // The old evaluator solved this performance issue by simply ignoring equality // for patterns. This led to duplicate disjunctions and incorrect results. // // The new evaluator computes the correct result, but is highly exponential. // The solution is probably to limit structural cycle depth. // // An alternative would be to stop processing disjunctions if we see there are // more than two solutions. This might still result in exponential behavior, // but will limit it considerably. nestedClosed: passing: { D: {id: {}} | {[string]: D} D: {id: {}} | {[string]: D} D: {id: {}} | {[string]: D} } -- out/evalalpha/stats -- Leaks: 1970 Freed: 573 Reused: 573 Allocs: 1970 Retain: 0 Unifications: 445 Conjuncts: 4775 Disjuncts: 818 -- out/evalalpha -- (struct){ #Secret: (#struct){ $secret: (#struct){ id: (string){ string } _id: (string){ string } } } #secrets: (#struct){ |((#struct){ $secret: (#struct){ id: (string){ string } _id: (string){ string } } }, (#struct){ }) } out: (#struct){ FOO: (#struct){ $secret: (#struct){ id: (string){ "100" } _id: (string){ "100" } } } ONE: (#struct){ TWO: (#struct){ THREE: (#struct){ $secret: (#struct){ id: (string){ "123" } _id: (string){ "123" } } } } } } nestedCross: (struct){ closed: (struct){ #D: (#struct){ |((#struct){ id: (string){ string } }, (#struct){ }) } } open: (struct){ D: (struct){ |((struct){ id: (string){ string } }, (struct){ }) } } } nestedClosed: (struct){ passing: (struct){ D: (struct){ |((struct){ id: (struct){ } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ }) } } } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 1064333 -Reused: 1064282 -Allocs: 51 +Leaks: 1970 +Freed: 573 +Reused: 573 +Allocs: 1970 Retain: 0 -Unifications: 792123 -Conjuncts: 2480117 -Disjuncts: 1064333 +Unifications: 445 +Conjuncts: 4775 +Disjuncts: 818 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -56,36 +56,6 @@ }, (struct){ }) } }, (struct){ - id: (struct){ |((struct){ - id: (struct){ - } - }, (struct){ - }) } - }, (struct){ - id: (struct){ |((struct){ - id: (struct){ - } - }, (struct){ - }) } - }, (struct){ - id: (struct){ |((struct){ - id: (struct){ - } - }, (struct){ - }) } - }, (struct){ - id: (struct){ |((struct){ - id: (struct){ - } - }, (struct){ - }) } - }, (struct){ - id: (struct){ |((struct){ - id: (struct){ - } - }, (struct){ - }) } - }, (struct){ }) } } } -- diff/explanation -- New algorithm is better at trimming recursive disjunctions. -- out/eval/stats -- Leaks: 0 Freed: 1064333 Reused: 1064282 Allocs: 51 Retain: 0 Unifications: 792123 Conjuncts: 2480117 Disjuncts: 1064333 -- out/eval -- (struct){ #Secret: (#struct){ $secret: (#struct){ id: (string){ string } _id: (string){ string } } } #secrets: (#struct){ |((#struct){ $secret: (#struct){ id: (string){ string } _id: (string){ string } } }, (#struct){ }) } out: (#struct){ FOO: (#struct){ $secret: (#struct){ id: (string){ "100" } _id: (string){ "100" } } } ONE: (#struct){ TWO: (#struct){ THREE: (#struct){ $secret: (#struct){ id: (string){ "123" } _id: (string){ "123" } } } } } } nestedCross: (struct){ closed: (struct){ #D: (#struct){ |((#struct){ id: (string){ string } }, (#struct){ }) } } open: (struct){ D: (struct){ |((struct){ id: (string){ string } }, (struct){ }) } } } nestedClosed: (struct){ passing: (struct){ D: (struct){ |((struct){ id: (struct){ } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ id: (struct){ |((struct){ id: (struct){ } }, (struct){ }) } }, (struct){ }) } } } } -- out/compile -- --- in.cue { #Secret: { $secret: { id: string } } #secrets: (〈0;#Secret〉|{ [string]: 〈1;#secrets〉 }) out: (〈0;#secrets〉 & { FOO: { $secret: { id: "100" } } ONE: { TWO: { THREE: { $secret: { id: "123" } } } } }) #Secret: { $secret: { _id: string } } #secrets: (〈0;#Secret〉|{ [string]: 〈1;#secrets〉 }) out: (〈0;#secrets〉 & { FOO: { $secret: { _id: "100" } } ONE: { TWO: { THREE: { $secret: { _id: "123" } } } } }) } --- perf.cue { nestedCross: { closed: { #D: ({ id: string }|{ [string]: 〈1;#D〉 }) #D: ({ id: string }|{ [string]: 〈1;#D〉 }) #D: ({ id: string }|{ [string]: 〈1;#D〉 }) } } nestedCross: { open: { D: ({ id: string }|{ [string]: 〈1;D〉 }) D: ({ id: string }|{ [string]: 〈1;D〉 }) D: ({ id: string }|{ [string]: 〈1;D〉 }) } } nestedClosed: { passing: { D: ({ id: {} }|{ [string]: 〈1;D〉 }) D: ({ id: {} }|{ [string]: 〈1;D〉 }) D: ({ id: {} }|{ [string]: 〈1;D〉 }) } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/issue2176.txtar000066400000000000000000001423531474664451600237460ustar00rootroot00000000000000-- stats.txt -- Leaks: 86 Freed: 3303 Reused: 3296 Allocs: 93 Retain: 525 Unifications: 3381 Conjuncts: 7871 Disjuncts: 3820 -- in.cue -- import ( "strings" "strconv" "list" ) #Datastream: { message: string message: strings.MinRunes(4) marker: { length: int position: { let characters = strings.Split(message, "") let unique_combinations = { // begin computation once we have more than x number of characters. for i, _ in characters if i >= length-1 { // this line is causing an increased evaluation time between cue versions. // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv let combination = list.Slice(characters, i-length+1, i+1) // last x number of characters are not unique. if list.UniqueItems(list.Slice(characters, i-length+1, i+1)) { "\(i+1)": combination } } } [for i, _ in unique_combinations {i}][0] } } } input_short: """ mjqjpqmgbljsphdztnvjfqwrcgsmlb """ input_long: """ qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw """ input: *input_short | input_long datastream: #Datastream & {message: input} output: [string]: string output: { "1": (datastream & {marker: length: 4}).marker.position "2": (datastream & {marker: length: 14}).marker.position } -- out/eval/stats -- Leaks: 90 Freed: 684 Reused: 680 Allocs: 94 Retain: 1359 Unifications: 766 Conjuncts: 3242 Disjuncts: 1409 -- out/evalalpha -- (struct){ #Datastream: (#struct){ message: (string){ strings.MinRunes(4) } marker: (#struct){ length: (int){ int } position: (_|_){ // [incomplete] #Datastream.marker.position.characters: error in call to strings.Split: non-concrete value string: // ./in.cue:14:21 // ./in.cue:9:11 let characters#1 = (_|_){ // [incomplete] #Datastream.marker.position.characters: error in call to strings.Split: non-concrete value string: // ./in.cue:14:21 // ./in.cue:9:11 } let unique_combinations#2 = (_|_){ // [incomplete] #Datastream.marker.position.characters: error in call to strings.Split: non-concrete value string: // ./in.cue:14:21 // ./in.cue:9:11 let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) } } } } input_short: (string){ "mjqjpqmgbljsphdztnvjfqwrcgsmlb" } input_long: (string){ "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" } input: (string){ |(*(string){ "mjqjpqmgbljsphdztnvjfqwrcgsmlb" }, (string){ "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" }) } datastream: (#struct){ message: (string){ |(*(string){ "mjqjpqmgbljsphdztnvjfqwrcgsmlb" }, (string){ "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" }) } marker: (#struct){ length: (int){ int } position: (_|_){ // [incomplete] datastream.marker.position.unique_combinations: non-concrete value int in operand to -: // ./in.cue:17:36 // ./in.cue:12:11 let characters#1 = (#list){ 0: (string){ "m" } 1: (string){ "j" } 2: (string){ "q" } 3: (string){ "j" } 4: (string){ "p" } 5: (string){ "q" } 6: (string){ "m" } 7: (string){ "g" } 8: (string){ "b" } 9: (string){ "l" } 10: (string){ "j" } 11: (string){ "s" } 12: (string){ "p" } 13: (string){ "h" } 14: (string){ "d" } 15: (string){ "z" } 16: (string){ "t" } 17: (string){ "n" } 18: (string){ "v" } 19: (string){ "j" } 20: (string){ "f" } 21: (string){ "q" } 22: (string){ "w" } 23: (string){ "r" } 24: (string){ "c" } 25: (string){ "g" } 26: (string){ "s" } 27: (string){ "m" } 28: (string){ "l" } 29: (string){ "b" } } let unique_combinations#2 = (_|_){ // [incomplete] datastream.marker.position.unique_combinations: non-concrete value int in operand to -: // ./in.cue:17:36 // ./in.cue:12:11 let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) } } } } output: (struct){ "1": (string){ "7" let characters#1 = (#list){ 0: (string){ "m" } 1: (string){ "j" } 2: (string){ "q" } 3: (string){ "j" } 4: (string){ "p" } 5: (string){ "q" } 6: (string){ "m" } 7: (string){ "g" } 8: (string){ "b" } 9: (string){ "l" } 10: (string){ "j" } 11: (string){ "s" } 12: (string){ "p" } 13: (string){ "h" } 14: (string){ "d" } 15: (string){ "z" } 16: (string){ "t" } 17: (string){ "n" } 18: (string){ "v" } 19: (string){ "j" } 20: (string){ "f" } 21: (string){ "q" } 22: (string){ "w" } 23: (string){ "r" } 24: (string){ "c" } 25: (string){ "g" } 26: (string){ "s" } 27: (string){ "m" } 28: (string){ "l" } 29: (string){ "b" } } let unique_combinations#2 = (#struct){ let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) "7": (#list){ 0: (string){ "j" } 1: (string){ "p" } 2: (string){ "q" } 3: (string){ "m" } } "8": (#list){ 0: (string){ "p" } 1: (string){ "q" } 2: (string){ "m" } 3: (string){ "g" } } "9": (#list){ 0: (string){ "q" } 1: (string){ "m" } 2: (string){ "g" } 3: (string){ "b" } } "10": (#list){ 0: (string){ "m" } 1: (string){ "g" } 2: (string){ "b" } 3: (string){ "l" } } "11": (#list){ 0: (string){ "g" } 1: (string){ "b" } 2: (string){ "l" } 3: (string){ "j" } } "12": (#list){ 0: (string){ "b" } 1: (string){ "l" } 2: (string){ "j" } 3: (string){ "s" } } "13": (#list){ 0: (string){ "l" } 1: (string){ "j" } 2: (string){ "s" } 3: (string){ "p" } } "14": (#list){ 0: (string){ "j" } 1: (string){ "s" } 2: (string){ "p" } 3: (string){ "h" } } "15": (#list){ 0: (string){ "s" } 1: (string){ "p" } 2: (string){ "h" } 3: (string){ "d" } } "16": (#list){ 0: (string){ "p" } 1: (string){ "h" } 2: (string){ "d" } 3: (string){ "z" } } "17": (#list){ 0: (string){ "h" } 1: (string){ "d" } 2: (string){ "z" } 3: (string){ "t" } } "18": (#list){ 0: (string){ "d" } 1: (string){ "z" } 2: (string){ "t" } 3: (string){ "n" } } "19": (#list){ 0: (string){ "z" } 1: (string){ "t" } 2: (string){ "n" } 3: (string){ "v" } } "20": (#list){ 0: (string){ "t" } 1: (string){ "n" } 2: (string){ "v" } 3: (string){ "j" } } "21": (#list){ 0: (string){ "n" } 1: (string){ "v" } 2: (string){ "j" } 3: (string){ "f" } } "22": (#list){ 0: (string){ "v" } 1: (string){ "j" } 2: (string){ "f" } 3: (string){ "q" } } "23": (#list){ 0: (string){ "j" } 1: (string){ "f" } 2: (string){ "q" } 3: (string){ "w" } } "24": (#list){ 0: (string){ "f" } 1: (string){ "q" } 2: (string){ "w" } 3: (string){ "r" } } "25": (#list){ 0: (string){ "q" } 1: (string){ "w" } 2: (string){ "r" } 3: (string){ "c" } } "26": (#list){ 0: (string){ "w" } 1: (string){ "r" } 2: (string){ "c" } 3: (string){ "g" } } "27": (#list){ 0: (string){ "r" } 1: (string){ "c" } 2: (string){ "g" } 3: (string){ "s" } } "28": (#list){ 0: (string){ "c" } 1: (string){ "g" } 2: (string){ "s" } 3: (string){ "m" } } "29": (#list){ 0: (string){ "g" } 1: (string){ "s" } 2: (string){ "m" } 3: (string){ "l" } } "30": (#list){ 0: (string){ "s" } 1: (string){ "m" } 2: (string){ "l" } 3: (string){ "b" } } } } "2": (string){ "19" let characters#1 = (#list){ 0: (string){ "m" } 1: (string){ "j" } 2: (string){ "q" } 3: (string){ "j" } 4: (string){ "p" } 5: (string){ "q" } 6: (string){ "m" } 7: (string){ "g" } 8: (string){ "b" } 9: (string){ "l" } 10: (string){ "j" } 11: (string){ "s" } 12: (string){ "p" } 13: (string){ "h" } 14: (string){ "d" } 15: (string){ "z" } 16: (string){ "t" } 17: (string){ "n" } 18: (string){ "v" } 19: (string){ "j" } 20: (string){ "f" } 21: (string){ "q" } 22: (string){ "w" } 23: (string){ "r" } 24: (string){ "c" } 25: (string){ "g" } 26: (string){ "s" } 27: (string){ "m" } 28: (string){ "l" } 29: (string){ "b" } } let unique_combinations#2 = (#struct){ let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) "19": (#list){ 0: (string){ "q" } 1: (string){ "m" } 2: (string){ "g" } 3: (string){ "b" } 4: (string){ "l" } 5: (string){ "j" } 6: (string){ "s" } 7: (string){ "p" } 8: (string){ "h" } 9: (string){ "d" } 10: (string){ "z" } 11: (string){ "t" } 12: (string){ "n" } 13: (string){ "v" } } "25": (#list){ 0: (string){ "s" } 1: (string){ "p" } 2: (string){ "h" } 3: (string){ "d" } 4: (string){ "z" } 5: (string){ "t" } 6: (string){ "n" } 7: (string){ "v" } 8: (string){ "j" } 9: (string){ "f" } 10: (string){ "q" } 11: (string){ "w" } 12: (string){ "r" } 13: (string){ "c" } } "26": (#list){ 0: (string){ "p" } 1: (string){ "h" } 2: (string){ "d" } 3: (string){ "z" } 4: (string){ "t" } 5: (string){ "n" } 6: (string){ "v" } 7: (string){ "j" } 8: (string){ "f" } 9: (string){ "q" } 10: (string){ "w" } 11: (string){ "r" } 12: (string){ "c" } 13: (string){ "g" } } "27": (#list){ 0: (string){ "h" } 1: (string){ "d" } 2: (string){ "z" } 3: (string){ "t" } 4: (string){ "n" } 5: (string){ "v" } 6: (string){ "j" } 7: (string){ "f" } 8: (string){ "q" } 9: (string){ "w" } 10: (string){ "r" } 11: (string){ "c" } 12: (string){ "g" } 13: (string){ "s" } } "28": (#list){ 0: (string){ "d" } 1: (string){ "z" } 2: (string){ "t" } 3: (string){ "n" } 4: (string){ "v" } 5: (string){ "j" } 6: (string){ "f" } 7: (string){ "q" } 8: (string){ "w" } 9: (string){ "r" } 10: (string){ "c" } 11: (string){ "g" } 12: (string){ "s" } 13: (string){ "m" } } "29": (#list){ 0: (string){ "z" } 1: (string){ "t" } 2: (string){ "n" } 3: (string){ "v" } 4: (string){ "j" } 5: (string){ "f" } 6: (string){ "q" } 7: (string){ "w" } 8: (string){ "r" } 9: (string){ "c" } 10: (string){ "g" } 11: (string){ "s" } 12: (string){ "m" } 13: (string){ "l" } } "30": (#list){ 0: (string){ "t" } 1: (string){ "n" } 2: (string){ "v" } 3: (string){ "j" } 4: (string){ "f" } 5: (string){ "q" } 6: (string){ "w" } 7: (string){ "r" } 8: (string){ "c" } 9: (string){ "g" } 10: (string){ "s" } 11: (string){ "m" } 12: (string){ "l" } 13: (string){ "b" } } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -12,13 +12,11 @@ // ./in.cue:14:21 // ./in.cue:9:11 } - let unique_combinations#2multi = { - for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { - let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) - if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { - "\((〈2;i〉 + 1))": 〈1;let combination#3〉 - } - } + let unique_combinations#2 = (_|_){ + // [incomplete] #Datastream.marker.position.characters: error in call to strings.Split: non-concrete value string: + // ./in.cue:14:21 + // ./in.cue:9:11 + let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) } } } @@ -66,13 +64,11 @@ 28: (string){ "l" } 29: (string){ "b" } } - let unique_combinations#2multi = { - for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { - let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) - if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { - "\((〈2;i〉 + 1))": 〈1;let combination#3〉 - } - } + let unique_combinations#2 = (_|_){ + // [incomplete] datastream.marker.position.unique_combinations: non-concrete value int in operand to -: + // ./in.cue:17:36 + // ./in.cue:12:11 + let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) } } } @@ -112,12 +108,151 @@ 28: (string){ "l" } 29: (string){ "b" } } - let unique_combinations#2multi = { - for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { - let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) - if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { - "\((〈2;i〉 + 1))": 〈1;let combination#3〉 - } + let unique_combinations#2 = (#struct){ + let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) + "7": (#list){ + 0: (string){ "j" } + 1: (string){ "p" } + 2: (string){ "q" } + 3: (string){ "m" } + } + "8": (#list){ + 0: (string){ "p" } + 1: (string){ "q" } + 2: (string){ "m" } + 3: (string){ "g" } + } + "9": (#list){ + 0: (string){ "q" } + 1: (string){ "m" } + 2: (string){ "g" } + 3: (string){ "b" } + } + "10": (#list){ + 0: (string){ "m" } + 1: (string){ "g" } + 2: (string){ "b" } + 3: (string){ "l" } + } + "11": (#list){ + 0: (string){ "g" } + 1: (string){ "b" } + 2: (string){ "l" } + 3: (string){ "j" } + } + "12": (#list){ + 0: (string){ "b" } + 1: (string){ "l" } + 2: (string){ "j" } + 3: (string){ "s" } + } + "13": (#list){ + 0: (string){ "l" } + 1: (string){ "j" } + 2: (string){ "s" } + 3: (string){ "p" } + } + "14": (#list){ + 0: (string){ "j" } + 1: (string){ "s" } + 2: (string){ "p" } + 3: (string){ "h" } + } + "15": (#list){ + 0: (string){ "s" } + 1: (string){ "p" } + 2: (string){ "h" } + 3: (string){ "d" } + } + "16": (#list){ + 0: (string){ "p" } + 1: (string){ "h" } + 2: (string){ "d" } + 3: (string){ "z" } + } + "17": (#list){ + 0: (string){ "h" } + 1: (string){ "d" } + 2: (string){ "z" } + 3: (string){ "t" } + } + "18": (#list){ + 0: (string){ "d" } + 1: (string){ "z" } + 2: (string){ "t" } + 3: (string){ "n" } + } + "19": (#list){ + 0: (string){ "z" } + 1: (string){ "t" } + 2: (string){ "n" } + 3: (string){ "v" } + } + "20": (#list){ + 0: (string){ "t" } + 1: (string){ "n" } + 2: (string){ "v" } + 3: (string){ "j" } + } + "21": (#list){ + 0: (string){ "n" } + 1: (string){ "v" } + 2: (string){ "j" } + 3: (string){ "f" } + } + "22": (#list){ + 0: (string){ "v" } + 1: (string){ "j" } + 2: (string){ "f" } + 3: (string){ "q" } + } + "23": (#list){ + 0: (string){ "j" } + 1: (string){ "f" } + 2: (string){ "q" } + 3: (string){ "w" } + } + "24": (#list){ + 0: (string){ "f" } + 1: (string){ "q" } + 2: (string){ "w" } + 3: (string){ "r" } + } + "25": (#list){ + 0: (string){ "q" } + 1: (string){ "w" } + 2: (string){ "r" } + 3: (string){ "c" } + } + "26": (#list){ + 0: (string){ "w" } + 1: (string){ "r" } + 2: (string){ "c" } + 3: (string){ "g" } + } + "27": (#list){ + 0: (string){ "r" } + 1: (string){ "c" } + 2: (string){ "g" } + 3: (string){ "s" } + } + "28": (#list){ + 0: (string){ "c" } + 1: (string){ "g" } + 2: (string){ "s" } + 3: (string){ "m" } + } + "29": (#list){ + 0: (string){ "g" } + 1: (string){ "s" } + 2: (string){ "m" } + 3: (string){ "l" } + } + "30": (#list){ + 0: (string){ "s" } + 1: (string){ "m" } + 2: (string){ "l" } + 3: (string){ "b" } } } } @@ -155,12 +290,119 @@ 28: (string){ "l" } 29: (string){ "b" } } - let unique_combinations#2multi = { - for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { - let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) - if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { - "\((〈2;i〉 + 1))": 〈1;let combination#3〉 - } + let unique_combinations#2 = (#struct){ + let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) + "19": (#list){ + 0: (string){ "q" } + 1: (string){ "m" } + 2: (string){ "g" } + 3: (string){ "b" } + 4: (string){ "l" } + 5: (string){ "j" } + 6: (string){ "s" } + 7: (string){ "p" } + 8: (string){ "h" } + 9: (string){ "d" } + 10: (string){ "z" } + 11: (string){ "t" } + 12: (string){ "n" } + 13: (string){ "v" } + } + "25": (#list){ + 0: (string){ "s" } + 1: (string){ "p" } + 2: (string){ "h" } + 3: (string){ "d" } + 4: (string){ "z" } + 5: (string){ "t" } + 6: (string){ "n" } + 7: (string){ "v" } + 8: (string){ "j" } + 9: (string){ "f" } + 10: (string){ "q" } + 11: (string){ "w" } + 12: (string){ "r" } + 13: (string){ "c" } + } + "26": (#list){ + 0: (string){ "p" } + 1: (string){ "h" } + 2: (string){ "d" } + 3: (string){ "z" } + 4: (string){ "t" } + 5: (string){ "n" } + 6: (string){ "v" } + 7: (string){ "j" } + 8: (string){ "f" } + 9: (string){ "q" } + 10: (string){ "w" } + 11: (string){ "r" } + 12: (string){ "c" } + 13: (string){ "g" } + } + "27": (#list){ + 0: (string){ "h" } + 1: (string){ "d" } + 2: (string){ "z" } + 3: (string){ "t" } + 4: (string){ "n" } + 5: (string){ "v" } + 6: (string){ "j" } + 7: (string){ "f" } + 8: (string){ "q" } + 9: (string){ "w" } + 10: (string){ "r" } + 11: (string){ "c" } + 12: (string){ "g" } + 13: (string){ "s" } + } + "28": (#list){ + 0: (string){ "d" } + 1: (string){ "z" } + 2: (string){ "t" } + 3: (string){ "n" } + 4: (string){ "v" } + 5: (string){ "j" } + 6: (string){ "f" } + 7: (string){ "q" } + 8: (string){ "w" } + 9: (string){ "r" } + 10: (string){ "c" } + 11: (string){ "g" } + 12: (string){ "s" } + 13: (string){ "m" } + } + "29": (#list){ + 0: (string){ "z" } + 1: (string){ "t" } + 2: (string){ "n" } + 3: (string){ "v" } + 4: (string){ "j" } + 5: (string){ "f" } + 6: (string){ "q" } + 7: (string){ "w" } + 8: (string){ "r" } + 9: (string){ "c" } + 10: (string){ "g" } + 11: (string){ "s" } + 12: (string){ "m" } + 13: (string){ "l" } + } + "30": (#list){ + 0: (string){ "t" } + 1: (string){ "n" } + 2: (string){ "v" } + 3: (string){ "j" } + 4: (string){ "f" } + 5: (string){ "q" } + 6: (string){ "w" } + 7: (string){ "r" } + 8: (string){ "c" } + 9: (string){ "g" } + 10: (string){ "s" } + 11: (string){ "m" } + 12: (string){ "l" } + 13: (string){ "b" } } } } -- diff/todo/p2 -- let unique_combinations: not marked as multi. Seems benign, but should be fixed. -- out/eval -- (struct){ #Datastream: (#struct){ message: (string){ strings.MinRunes(4) } marker: (#struct){ length: (int){ int } position: (_|_){ // [incomplete] #Datastream.marker.position.characters: error in call to strings.Split: non-concrete value string: // ./in.cue:14:21 // ./in.cue:9:11 let characters#1 = (_|_){ // [incomplete] #Datastream.marker.position.characters: error in call to strings.Split: non-concrete value string: // ./in.cue:14:21 // ./in.cue:9:11 } let unique_combinations#2multi = { for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { "\((〈2;i〉 + 1))": 〈1;let combination#3〉 } } } } } } input_short: (string){ "mjqjpqmgbljsphdztnvjfqwrcgsmlb" } input_long: (string){ "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" } input: (string){ |(*(string){ "mjqjpqmgbljsphdztnvjfqwrcgsmlb" }, (string){ "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" }) } datastream: (#struct){ message: (string){ |(*(string){ "mjqjpqmgbljsphdztnvjfqwrcgsmlb" }, (string){ "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" }) } marker: (#struct){ length: (int){ int } position: (_|_){ // [incomplete] datastream.marker.position.unique_combinations: non-concrete value int in operand to -: // ./in.cue:17:36 // ./in.cue:12:11 let characters#1 = (#list){ 0: (string){ "m" } 1: (string){ "j" } 2: (string){ "q" } 3: (string){ "j" } 4: (string){ "p" } 5: (string){ "q" } 6: (string){ "m" } 7: (string){ "g" } 8: (string){ "b" } 9: (string){ "l" } 10: (string){ "j" } 11: (string){ "s" } 12: (string){ "p" } 13: (string){ "h" } 14: (string){ "d" } 15: (string){ "z" } 16: (string){ "t" } 17: (string){ "n" } 18: (string){ "v" } 19: (string){ "j" } 20: (string){ "f" } 21: (string){ "q" } 22: (string){ "w" } 23: (string){ "r" } 24: (string){ "c" } 25: (string){ "g" } 26: (string){ "s" } 27: (string){ "m" } 28: (string){ "l" } 29: (string){ "b" } } let unique_combinations#2multi = { for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { "\((〈2;i〉 + 1))": 〈1;let combination#3〉 } } } } } } output: (struct){ "1": (string){ "7" let characters#1 = (#list){ 0: (string){ "m" } 1: (string){ "j" } 2: (string){ "q" } 3: (string){ "j" } 4: (string){ "p" } 5: (string){ "q" } 6: (string){ "m" } 7: (string){ "g" } 8: (string){ "b" } 9: (string){ "l" } 10: (string){ "j" } 11: (string){ "s" } 12: (string){ "p" } 13: (string){ "h" } 14: (string){ "d" } 15: (string){ "z" } 16: (string){ "t" } 17: (string){ "n" } 18: (string){ "v" } 19: (string){ "j" } 20: (string){ "f" } 21: (string){ "q" } 22: (string){ "w" } 23: (string){ "r" } 24: (string){ "c" } 25: (string){ "g" } 26: (string){ "s" } 27: (string){ "m" } 28: (string){ "l" } 29: (string){ "b" } } let unique_combinations#2multi = { for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { "\((〈2;i〉 + 1))": 〈1;let combination#3〉 } } } } "2": (string){ "19" let characters#1 = (#list){ 0: (string){ "m" } 1: (string){ "j" } 2: (string){ "q" } 3: (string){ "j" } 4: (string){ "p" } 5: (string){ "q" } 6: (string){ "m" } 7: (string){ "g" } 8: (string){ "b" } 9: (string){ "l" } 10: (string){ "j" } 11: (string){ "s" } 12: (string){ "p" } 13: (string){ "h" } 14: (string){ "d" } 15: (string){ "z" } 16: (string){ "t" } 17: (string){ "n" } 18: (string){ "v" } 19: (string){ "j" } 20: (string){ "f" } 21: (string){ "q" } 22: (string){ "w" } 23: (string){ "r" } 24: (string){ "c" } 25: (string){ "g" } 26: (string){ "s" } 27: (string){ "m" } 28: (string){ "l" } 29: (string){ "b" } } let unique_combinations#2multi = { for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { "\((〈2;i〉 + 1))": 〈1;let combination#3〉 } } } } } } -- out/compile -- --- in.cue { #Datastream: { message: string message: 〈import;strings〉.MinRunes(4) marker: { length: int position: { let characters#1 = 〈import;strings〉.Split(〈2;message〉, "") let unique_combinations#2multi = { for i, _ in 〈1;let characters#1〉 if (〈0;i〉 >= (〈3;length〉 - 1)) { let combination#3multi = 〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1)) if 〈import;list〉.UniqueItems(〈import;list〉.Slice(〈3;let characters#1〉, ((〈1;i〉 - 〈4;length〉) + 1), (〈1;i〉 + 1))) { "\((〈2;i〉 + 1))": 〈1;let combination#3〉 } } } [ for i, _ in 〈1;let unique_combinations#2〉 { 〈1;i〉 }, ][0] } } } input_short: "mjqjpqmgbljsphdztnvjfqwrcgsmlb" input_long: "qfmfhmhjmjggwbbvdvwvlvrrtsrsccwsslvlffjrrtprprjjvmmclmmghhddpvddclctcqtccgbgdbgdgsdgghqhtqtvvptvppwrwprpvrrrhpphththvhhrnnhnlnslnlhnhnhgnhnpnqqsmsgsllprlprrlzzqzffmzztctbtnbtthlttqvqcqmcmpcpbbczzbqbgghcghchhvwvllfrfnnbssfzsszpsplpglpprnpnfnbnhbnbtbzzvbvpbbhjjlzzbtbvbppczppbwppqwwnwlwccglgvgrgmmdwmwrmrppnfnhhhhqthqthqqrhrshhhqbhqqjgjvjllzvzbzhbbpttjsszvzqqtzzmbmddpldpdcdnccrmcrmmpwprplrrqssvddmpdmmwfwwlrljrrdsssmhsspnpffjggqllnzlnlhnnmddfrfpfbbvssjsrrznngcghgchcmhmrrrtzztjzzhchssslsmlmvvpwpqpjqjdddmsdmmtgtmgtglttfbbgrrcprrqffmmjnjttcmczzgbzggthhsttpggrmmgwwnpnqnqvnqvqppmlpmlpmpjpljljmmtpptfppfrppfdpfdppddmdttgzgzzdbzdzhzhnnsqssvmvbbpjjzwwvnwvvzmvzmzpmpttvrvccqddpgdppgmmthmthtggsfsbbvfbvfvhfvhvvpwpddqrqgqhghnnfmfbbwrbrgbgbvgbbdttffrddqbqpqzzmttlhhsqhsqhsqhhlplttpnpsstpthhpfhpfplprrgfrgffjppghgppghgdggjmmcgmccjvvsrvsrrwgrgmrrngrgttvbtbltthrthrttmfffjpfpssncnrngrrltrltlggjgcgllrzzllhwwjwrwgrgsrgrhrphrhhqwqsqmqlmqlmqmqrmrnnwnhwnhwhzwzjwwgbghhsjspszsznzfztfzfpzzlczztctsstctqtfqfqcfqqjrjccttmqqfpfdfnfwnffqbfbblpbpfpcfcwfccblbwwmqwqrrgprpccngnhghpppwmpplcppfrfjjgmmbzbhbcbzzgdgsdsvvqllzlppnfnlnlslsljlppcscqqfjjjwzwppfgfjjsvvsggjbjljpjpzjzrzjrzzfnfpnfpnfpnfnsnggmpggdllpmmrhhdqqppttgqqcsqsjsbjsjrsrqrbqqmbmcbmcbmbfmfvfqqdbdppmrprnrggmjjhnhbhdhbbfcbbcjjdhhwjwmjmssjswscswcwzccbgbqqmqgmmsdsjsbsdbsddvttjpppcqpcqcgqqslqsssczszrzvvrtvvjppswwhnnwlwtwhhwwzfwwpfpddlvvnvnnvlnntjtqjqjzzjttvvbqbhqbhbbbwnwhnwnppdbpdpvddrqdqjjlvlqqdfdhdjhdjdcjcrcjjggfmfvvfllvfvgglzllmhmzmdddfwddqjjqjfqfcfrrstrssptsstllrflfwwgswslwlbwbwjjvhvfvhfhffhsslwsllbnbblccbwwjqwqqdllrdrnrnffcbbqqpnqqdmdndtntvvrjvvsvmvgvnnmjlwgnjcwljgwnrwpqlztwrpmpgqtwlhrcwsrrhqhjhznrtpqfdnzbfqrzwslptdbdcnqvcllpjsfdvmzqwvzbpnmfcfcjnbmhtwhttjgtnczwctpdthhwmzvzrrgsnmbflgmszgsbvghbzgcmcmszgsbfmlmpbdspqlftmqrcjtmvgcrzznlfwjcbmddplsqrfflqnqfsldwhnncczdmfrrrsbjjqsdzrsgbdbwjbslfcqglsqfddhdsrcdrgqfqthgmfjvnfdfgdncfzpvqcpscnpmfgvqbfwszwzgmqvmcrdrwplfshdgqrchmccpqfznbmfvlhdpctlqgjslrwhjfjlmqfblgjrdlnzdtwlpwhnrhrcrpfwqpmjlgrdbgpbljntmbqlblqqqpgrnjtmjqvjpzvsqdpgtchmmwbhtmgcjqdplrtptqcvdjjpqdzsrcjhcwvdcghlwrdhtdfctmqfcjcqhcvvbzgsvlggcrdgqbtznwwmnbgsfrjprqgcmlswftlwpqqqvshdprldrsghmhrqvmqmvglbvzpvtrjbhcvhqmvdtcvsllznqzjmhpnlbhmlzthbwwhhvdtcdfdcdzhnbsrnqqjvzzsvfjhbsdlsbdlqjnlpnhfcjtdppzmphghltztzcdvzwbftbvwhvgmrllqfzrpbltptdtjjqtfwjfmczzgdvclqbsbftgtlhnhrrvbpvdltstdnhqvpvtjhmghptvsfnlspslmfsftzdrwljrgblgmcbmlszmhnlfdtmsrnjqwrfmsnfgpcqgzmlwppffrmbvhnlstfpgzw" input: (*〈0;input_short〉|〈0;input_long〉) datastream: (〈0;#Datastream〉 & { message: 〈1;input〉 }) output: { [string]: string } output: { "1": (〈1;datastream〉 & { marker: { length: 4 } }).marker.position "2": (〈1;datastream〉 & { marker: { length: 14 } }).marker.position } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/issue3307.txtar000066400000000000000000000015651474664451600237420ustar00rootroot00000000000000-- in.cue -- if _request.enabled { r1: { k1: 0 k2: 0 k3: 0 k4: 0 k5: 0 k6: 0 k7: 0 k8: 0 k9: 0 k10: 0 k11: 0 k12: 0 k13: 0 k14: 0 k15: 0 k16: 0 k17: 0 } } _request: enabled: _ -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 16 Allocs: 5 Retain: 72 Unifications: 21 Conjuncts: 3 Disjuncts: 93 -- out/eval -- (_|_){ // [incomplete] incomplete bool: _ _request: (struct){ enabled: (_){ _ } } } -- out/compile -- --- in.cue { if 〈0;_request〉.enabled { r1: { k1: 0 k2: 0 k3: 0 k4: 0 k5: 0 k6: 0 k7: 0 k8: 0 k9: 0 k10: 0 k11: 0 k12: 0 k13: 0 k14: 0 k15: 0 k16: 0 k17: 0 } } _request: { enabled: _ } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/issue3517.txtar000066400000000000000000000372661474664451600237540ustar00rootroot00000000000000-- main.cue -- package p #TimeSpan: { start: float duration: float end: float start: end - duration duration: end - start end: start + duration start: <=end } #Task: { action: string timeSpan: #TimeSpan } #TaskSet: { action: string #tasks: [string]: #Task tasks: [for _, v in #tasks {v}] tasks: [...#Task] timeSpan?: #TimeSpan } #T1: #Task & { action: "Task 1" timeSpan: #TimeSpan & { duration: 4.2 } } #T2: #Task & { action: "Task 2" timeSpan: #TimeSpan & { duration: 120.0 } } ts: #TaskSet ts: this={ action: "Task 1 and Task 2" #tasks: { t1: #T1 & { timeSpan: end: this.#tasks.t2.timeSpan.start } t2: #T2 & { timeSpan: end: 119 // this.timeSpan.end } } timeSpan: start: this.#tasks.t1.timeSpan.start } -- out/eval/stats -- Leaks: 2 Freed: 49 Reused: 39 Allocs: 12 Retain: 608 Unifications: 51 Conjuncts: 801 Disjuncts: 73 -- out/evalalpha -- Errors: ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): ./main.cue:6:12 ./main.cue:50:19 Result: (_|_){ // [eval] #TimeSpan: (#struct){ start: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 // cycle error: // ./main.cue:10:12 } duration: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 } end: (_|_){ // [cycle] cycle error: // ./main.cue:10:12 } } #Task: (#struct){ action: (string){ string } timeSpan: ~(#TimeSpan) } #TaskSet: (#struct){ action: (string){ string } #tasks: (#struct){ } tasks: (#list){ } timeSpan?: ~(#TimeSpan) } #T1: (#struct){ action: (string){ "Task 1" } timeSpan: (#struct){ duration: (_|_){ // [cycle] cycle error } start: (_|_){ // [cycle] cycle error } end: (_|_){ // [cycle] cycle error } } } #T2: (#struct){ action: (string){ "Task 2" } timeSpan: (#struct){ duration: (_|_){ // [cycle] cycle error } start: (_|_){ // [cycle] cycle error } end: (_|_){ // [cycle] cycle error } } } ts: (_|_){ // [eval] action: (string){ "Task 1 and Task 2" } #tasks: (_|_){ // [eval] t1: (_|_){ // [eval] timeSpan: (_|_){ // [eval] end: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } duration: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } start: (_|_){ // [cycle] cycle error } } action: (string){ "Task 1" } } t2: (_|_){ // [eval] timeSpan: (_|_){ // [eval] end: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } duration: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } start: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } } action: (string){ "Task 2" } } } timeSpan: (_|_){ // [eval] start: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } duration: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } end: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } } tasks: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:50:19 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,6 @@ Errors: ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): ./main.cue:6:12 - ./main.cue:17:12 - ./main.cue:35:6 - ./main.cue:49:7 ./main.cue:50:19 Result: @@ -11,7 +8,10 @@ // [eval] #TimeSpan: (#struct){ start: (_|_){ - // [cycle] cycle error + // [cycle] cycle error: + // ./main.cue:9:12 + // cycle error: + // ./main.cue:10:12 } duration: (_|_){ // [cycle] cycle error: @@ -24,19 +24,7 @@ } #Task: (#struct){ action: (string){ string } - timeSpan: (#struct){ - start: (_|_){ - // [cycle] cycle error - } - duration: (_|_){ - // [cycle] cycle error: - // ./main.cue:9:12 - } - end: (_|_){ - // [cycle] cycle error: - // ./main.cue:10:12 - } - } + timeSpan: ~(#TimeSpan) } #TaskSet: (#struct){ action: (string){ string } @@ -44,29 +32,16 @@ } tasks: (#list){ } - timeSpan?: (#struct){ - start: (_|_){ - // [cycle] cycle error - } - duration: (_|_){ - // [cycle] cycle error: - // ./main.cue:9:12 - } - end: (_|_){ - // [cycle] cycle error: - // ./main.cue:10:12 - } - } + timeSpan?: ~(#TimeSpan) } #T1: (#struct){ action: (string){ "Task 1" } timeSpan: (#struct){ - start: (_|_){ - // [cycle] cycle error - } - duration: (_|_){ - // [cycle] cycle error: - // ./main.cue:9:12 + duration: (_|_){ + // [cycle] cycle error + } + start: (_|_){ + // [cycle] cycle error } end: (_|_){ // [cycle] cycle error @@ -76,12 +51,11 @@ #T2: (#struct){ action: (string){ "Task 2" } timeSpan: (#struct){ - start: (_|_){ - // [cycle] cycle error - } - duration: (_|_){ - // [cycle] cycle error: - // ./main.cue:9:12 + duration: (_|_){ + // [cycle] cycle error + } + start: (_|_){ + // [cycle] cycle error } end: (_|_){ // [cycle] cycle error @@ -93,66 +67,71 @@ action: (string){ "Task 1 and Task 2" } #tasks: (_|_){ // [eval] - t1: (#struct){ + t1: (_|_){ + // [eval] + timeSpan: (_|_){ + // [eval] + end: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + duration: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + start: (_|_){ + // [cycle] cycle error + } + } action: (string){ "Task 1" } - timeSpan: (#struct){ - start: (float){ -5.2 } - duration: (float){ 4.2 } - end: (float){ -1.0 } - } } t2: (_|_){ // [eval] + timeSpan: (_|_){ + // [eval] + end: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + duration: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + start: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + } action: (string){ "Task 2" } - timeSpan: (_|_){ - // [eval] - start: (float){ -1.0 } - duration: (float){ 120.0 } - end: (_|_){ - // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): - // ./main.cue:6:12 - // ./main.cue:17:12 - // ./main.cue:35:6 - // ./main.cue:49:7 - // ./main.cue:50:19 - } - } + } + } + timeSpan: (_|_){ + // [eval] + start: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + duration: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 + } + end: (_|_){ + // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): + // ./main.cue:6:12 + // ./main.cue:50:19 } } tasks: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 - // ./main.cue:17:12 - // ./main.cue:35:6 - // ./main.cue:49:7 // ./main.cue:50:19 } - timeSpan: (_|_){ - // [eval] - start: (_|_){ - // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): - // ./main.cue:6:12 - // ./main.cue:17:12 - // ./main.cue:35:6 - // ./main.cue:49:7 - // ./main.cue:50:19 - } - duration: (_|_){ - // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): - // ./main.cue:6:12 - // ./main.cue:17:12 - // ./main.cue:35:6 - // ./main.cue:49:7 - // ./main.cue:50:19 - } - end: (_|_){ - // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): - // ./main.cue:6:12 - // ./main.cue:17:12 - // ./main.cue:35:6 - // ./main.cue:49:7 - // ./main.cue:50:19 - } - } } } -- out/eval -- Errors: ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): ./main.cue:6:12 ./main.cue:17:12 ./main.cue:35:6 ./main.cue:49:7 ./main.cue:50:19 Result: (_|_){ // [eval] #TimeSpan: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 } end: (_|_){ // [cycle] cycle error: // ./main.cue:10:12 } } #Task: (#struct){ action: (string){ string } timeSpan: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 } end: (_|_){ // [cycle] cycle error: // ./main.cue:10:12 } } } #TaskSet: (#struct){ action: (string){ string } #tasks: (#struct){ } tasks: (#list){ } timeSpan?: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 } end: (_|_){ // [cycle] cycle error: // ./main.cue:10:12 } } } #T1: (#struct){ action: (string){ "Task 1" } timeSpan: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 } end: (_|_){ // [cycle] cycle error } } } #T2: (#struct){ action: (string){ "Task 2" } timeSpan: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./main.cue:9:12 } end: (_|_){ // [cycle] cycle error } } } ts: (_|_){ // [eval] action: (string){ "Task 1 and Task 2" } #tasks: (_|_){ // [eval] t1: (#struct){ action: (string){ "Task 1" } timeSpan: (#struct){ start: (float){ -5.2 } duration: (float){ 4.2 } end: (float){ -1.0 } } } t2: (_|_){ // [eval] action: (string){ "Task 2" } timeSpan: (_|_){ // [eval] start: (float){ -1.0 } duration: (float){ 120.0 } end: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:17:12 // ./main.cue:35:6 // ./main.cue:49:7 // ./main.cue:50:19 } } } } tasks: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:17:12 // ./main.cue:35:6 // ./main.cue:49:7 // ./main.cue:50:19 } timeSpan: (_|_){ // [eval] start: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:17:12 // ./main.cue:35:6 // ./main.cue:49:7 // ./main.cue:50:19 } duration: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:17:12 // ./main.cue:35:6 // ./main.cue:49:7 // ./main.cue:50:19 } end: (_|_){ // [eval] ts.#tasks.t2.timeSpan.end: conflicting values 119 and float (mismatched types int and float): // ./main.cue:6:12 // ./main.cue:17:12 // ./main.cue:35:6 // ./main.cue:49:7 // ./main.cue:50:19 } } } } -- out/compile -- --- main.cue { #TimeSpan: { start: float duration: float end: float start: (〈0;end〉 - 〈0;duration〉) duration: (〈0;end〉 - 〈0;start〉) end: (〈0;start〉 + 〈0;duration〉) start: <=〈0;end〉 } #Task: { action: string timeSpan: 〈1;#TimeSpan〉 } #TaskSet: { action: string #tasks: { [string]: 〈2;#Task〉 } tasks: [ for _, v in 〈1;#tasks〉 { 〈1;v〉 }, ] tasks: [ ...〈2;#Task〉, ] timeSpan?: 〈1;#TimeSpan〉 } #T1: (〈0;#Task〉 & { action: "Task 1" timeSpan: (〈1;#TimeSpan〉 & { duration: 4.2 }) }) #T2: (〈0;#Task〉 & { action: "Task 2" timeSpan: (〈1;#TimeSpan〉 & { duration: 120.0 }) }) ts: 〈0;#TaskSet〉 ts: { action: "Task 1 and Task 2" #tasks: { t1: (〈2;#T1〉 & { timeSpan: { end: 〈4〉.#tasks.t2.timeSpan.start } }) t2: (〈2;#T2〉 & { timeSpan: { end: 119 } }) } timeSpan: { start: 〈2〉.#tasks.t1.timeSpan.start } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/issue572.txtar000066400000000000000000002177551474664451600236750ustar00rootroot00000000000000-- in.cue -- package p import "list" _entries: [for i in list.Range(1, 1500, 1) {i}] unified: { for entry in _entries { "\(entry)": true } } -- out/eval/stats -- Leaks: 0 Freed: 3001 Reused: 2998 Allocs: 3 Retain: 0 Unifications: 3001 Conjuncts: 7498 Disjuncts: 3001 -- out/eval -- (struct){ _entries(:p): (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } 3: (int){ 4 } 4: (int){ 5 } 5: (int){ 6 } 6: (int){ 7 } 7: (int){ 8 } 8: (int){ 9 } 9: (int){ 10 } 10: (int){ 11 } 11: (int){ 12 } 12: (int){ 13 } 13: (int){ 14 } 14: (int){ 15 } 15: (int){ 16 } 16: (int){ 17 } 17: (int){ 18 } 18: (int){ 19 } 19: (int){ 20 } 20: (int){ 21 } 21: (int){ 22 } 22: (int){ 23 } 23: (int){ 24 } 24: (int){ 25 } 25: (int){ 26 } 26: (int){ 27 } 27: (int){ 28 } 28: (int){ 29 } 29: (int){ 30 } 30: (int){ 31 } 31: (int){ 32 } 32: (int){ 33 } 33: (int){ 34 } 34: (int){ 35 } 35: (int){ 36 } 36: (int){ 37 } 37: (int){ 38 } 38: (int){ 39 } 39: (int){ 40 } 40: (int){ 41 } 41: (int){ 42 } 42: (int){ 43 } 43: (int){ 44 } 44: (int){ 45 } 45: (int){ 46 } 46: (int){ 47 } 47: (int){ 48 } 48: (int){ 49 } 49: (int){ 50 } 50: (int){ 51 } 51: (int){ 52 } 52: (int){ 53 } 53: (int){ 54 } 54: (int){ 55 } 55: (int){ 56 } 56: (int){ 57 } 57: (int){ 58 } 58: (int){ 59 } 59: (int){ 60 } 60: (int){ 61 } 61: (int){ 62 } 62: (int){ 63 } 63: (int){ 64 } 64: (int){ 65 } 65: (int){ 66 } 66: (int){ 67 } 67: (int){ 68 } 68: (int){ 69 } 69: (int){ 70 } 70: (int){ 71 } 71: (int){ 72 } 72: (int){ 73 } 73: (int){ 74 } 74: (int){ 75 } 75: (int){ 76 } 76: (int){ 77 } 77: (int){ 78 } 78: (int){ 79 } 79: (int){ 80 } 80: (int){ 81 } 81: (int){ 82 } 82: (int){ 83 } 83: (int){ 84 } 84: (int){ 85 } 85: (int){ 86 } 86: (int){ 87 } 87: (int){ 88 } 88: (int){ 89 } 89: (int){ 90 } 90: (int){ 91 } 91: (int){ 92 } 92: (int){ 93 } 93: (int){ 94 } 94: (int){ 95 } 95: (int){ 96 } 96: (int){ 97 } 97: (int){ 98 } 98: (int){ 99 } 99: (int){ 100 } 100: (int){ 101 } 101: (int){ 102 } 102: (int){ 103 } 103: (int){ 104 } 104: (int){ 105 } 105: (int){ 106 } 106: (int){ 107 } 107: (int){ 108 } 108: (int){ 109 } 109: (int){ 110 } 110: (int){ 111 } 111: (int){ 112 } 112: (int){ 113 } 113: (int){ 114 } 114: (int){ 115 } 115: (int){ 116 } 116: (int){ 117 } 117: (int){ 118 } 118: (int){ 119 } 119: (int){ 120 } 120: (int){ 121 } 121: (int){ 122 } 122: (int){ 123 } 123: (int){ 124 } 124: (int){ 125 } 125: (int){ 126 } 126: (int){ 127 } 127: (int){ 128 } 128: (int){ 129 } 129: (int){ 130 } 130: (int){ 131 } 131: (int){ 132 } 132: (int){ 133 } 133: (int){ 134 } 134: (int){ 135 } 135: (int){ 136 } 136: (int){ 137 } 137: (int){ 138 } 138: (int){ 139 } 139: (int){ 140 } 140: (int){ 141 } 141: (int){ 142 } 142: (int){ 143 } 143: (int){ 144 } 144: (int){ 145 } 145: (int){ 146 } 146: (int){ 147 } 147: (int){ 148 } 148: (int){ 149 } 149: (int){ 150 } 150: (int){ 151 } 151: (int){ 152 } 152: (int){ 153 } 153: (int){ 154 } 154: (int){ 155 } 155: (int){ 156 } 156: (int){ 157 } 157: (int){ 158 } 158: (int){ 159 } 159: (int){ 160 } 160: (int){ 161 } 161: (int){ 162 } 162: (int){ 163 } 163: (int){ 164 } 164: (int){ 165 } 165: (int){ 166 } 166: (int){ 167 } 167: (int){ 168 } 168: (int){ 169 } 169: (int){ 170 } 170: (int){ 171 } 171: (int){ 172 } 172: (int){ 173 } 173: (int){ 174 } 174: (int){ 175 } 175: (int){ 176 } 176: (int){ 177 } 177: (int){ 178 } 178: (int){ 179 } 179: (int){ 180 } 180: (int){ 181 } 181: (int){ 182 } 182: (int){ 183 } 183: (int){ 184 } 184: (int){ 185 } 185: (int){ 186 } 186: (int){ 187 } 187: (int){ 188 } 188: (int){ 189 } 189: (int){ 190 } 190: (int){ 191 } 191: (int){ 192 } 192: (int){ 193 } 193: (int){ 194 } 194: (int){ 195 } 195: (int){ 196 } 196: (int){ 197 } 197: (int){ 198 } 198: (int){ 199 } 199: (int){ 200 } 200: (int){ 201 } 201: (int){ 202 } 202: (int){ 203 } 203: (int){ 204 } 204: (int){ 205 } 205: (int){ 206 } 206: (int){ 207 } 207: (int){ 208 } 208: (int){ 209 } 209: (int){ 210 } 210: (int){ 211 } 211: (int){ 212 } 212: (int){ 213 } 213: (int){ 214 } 214: (int){ 215 } 215: (int){ 216 } 216: (int){ 217 } 217: (int){ 218 } 218: (int){ 219 } 219: (int){ 220 } 220: (int){ 221 } 221: (int){ 222 } 222: (int){ 223 } 223: (int){ 224 } 224: (int){ 225 } 225: (int){ 226 } 226: (int){ 227 } 227: (int){ 228 } 228: (int){ 229 } 229: (int){ 230 } 230: (int){ 231 } 231: (int){ 232 } 232: (int){ 233 } 233: (int){ 234 } 234: (int){ 235 } 235: (int){ 236 } 236: (int){ 237 } 237: (int){ 238 } 238: (int){ 239 } 239: (int){ 240 } 240: (int){ 241 } 241: (int){ 242 } 242: (int){ 243 } 243: (int){ 244 } 244: (int){ 245 } 245: (int){ 246 } 246: (int){ 247 } 247: (int){ 248 } 248: (int){ 249 } 249: (int){ 250 } 250: (int){ 251 } 251: (int){ 252 } 252: (int){ 253 } 253: (int){ 254 } 254: (int){ 255 } 255: (int){ 256 } 256: (int){ 257 } 257: (int){ 258 } 258: (int){ 259 } 259: (int){ 260 } 260: (int){ 261 } 261: (int){ 262 } 262: (int){ 263 } 263: (int){ 264 } 264: (int){ 265 } 265: (int){ 266 } 266: (int){ 267 } 267: (int){ 268 } 268: (int){ 269 } 269: (int){ 270 } 270: (int){ 271 } 271: (int){ 272 } 272: (int){ 273 } 273: (int){ 274 } 274: (int){ 275 } 275: (int){ 276 } 276: (int){ 277 } 277: (int){ 278 } 278: (int){ 279 } 279: (int){ 280 } 280: (int){ 281 } 281: (int){ 282 } 282: (int){ 283 } 283: (int){ 284 } 284: (int){ 285 } 285: (int){ 286 } 286: (int){ 287 } 287: (int){ 288 } 288: (int){ 289 } 289: (int){ 290 } 290: (int){ 291 } 291: (int){ 292 } 292: (int){ 293 } 293: (int){ 294 } 294: (int){ 295 } 295: (int){ 296 } 296: (int){ 297 } 297: (int){ 298 } 298: (int){ 299 } 299: (int){ 300 } 300: (int){ 301 } 301: (int){ 302 } 302: (int){ 303 } 303: (int){ 304 } 304: (int){ 305 } 305: (int){ 306 } 306: (int){ 307 } 307: (int){ 308 } 308: (int){ 309 } 309: (int){ 310 } 310: (int){ 311 } 311: (int){ 312 } 312: (int){ 313 } 313: (int){ 314 } 314: (int){ 315 } 315: (int){ 316 } 316: (int){ 317 } 317: (int){ 318 } 318: (int){ 319 } 319: (int){ 320 } 320: (int){ 321 } 321: (int){ 322 } 322: (int){ 323 } 323: (int){ 324 } 324: (int){ 325 } 325: (int){ 326 } 326: (int){ 327 } 327: (int){ 328 } 328: (int){ 329 } 329: (int){ 330 } 330: (int){ 331 } 331: (int){ 332 } 332: (int){ 333 } 333: (int){ 334 } 334: (int){ 335 } 335: (int){ 336 } 336: (int){ 337 } 337: (int){ 338 } 338: (int){ 339 } 339: (int){ 340 } 340: (int){ 341 } 341: (int){ 342 } 342: (int){ 343 } 343: (int){ 344 } 344: (int){ 345 } 345: (int){ 346 } 346: (int){ 347 } 347: (int){ 348 } 348: (int){ 349 } 349: (int){ 350 } 350: (int){ 351 } 351: (int){ 352 } 352: (int){ 353 } 353: (int){ 354 } 354: (int){ 355 } 355: (int){ 356 } 356: (int){ 357 } 357: (int){ 358 } 358: (int){ 359 } 359: (int){ 360 } 360: (int){ 361 } 361: (int){ 362 } 362: (int){ 363 } 363: (int){ 364 } 364: (int){ 365 } 365: (int){ 366 } 366: (int){ 367 } 367: (int){ 368 } 368: (int){ 369 } 369: (int){ 370 } 370: (int){ 371 } 371: (int){ 372 } 372: (int){ 373 } 373: (int){ 374 } 374: (int){ 375 } 375: (int){ 376 } 376: (int){ 377 } 377: (int){ 378 } 378: (int){ 379 } 379: (int){ 380 } 380: (int){ 381 } 381: (int){ 382 } 382: (int){ 383 } 383: (int){ 384 } 384: (int){ 385 } 385: (int){ 386 } 386: (int){ 387 } 387: (int){ 388 } 388: (int){ 389 } 389: (int){ 390 } 390: (int){ 391 } 391: (int){ 392 } 392: (int){ 393 } 393: (int){ 394 } 394: (int){ 395 } 395: (int){ 396 } 396: (int){ 397 } 397: (int){ 398 } 398: (int){ 399 } 399: (int){ 400 } 400: (int){ 401 } 401: (int){ 402 } 402: (int){ 403 } 403: (int){ 404 } 404: (int){ 405 } 405: (int){ 406 } 406: (int){ 407 } 407: (int){ 408 } 408: (int){ 409 } 409: (int){ 410 } 410: (int){ 411 } 411: (int){ 412 } 412: (int){ 413 } 413: (int){ 414 } 414: (int){ 415 } 415: (int){ 416 } 416: (int){ 417 } 417: (int){ 418 } 418: (int){ 419 } 419: (int){ 420 } 420: (int){ 421 } 421: (int){ 422 } 422: (int){ 423 } 423: (int){ 424 } 424: (int){ 425 } 425: (int){ 426 } 426: (int){ 427 } 427: (int){ 428 } 428: (int){ 429 } 429: (int){ 430 } 430: (int){ 431 } 431: (int){ 432 } 432: (int){ 433 } 433: (int){ 434 } 434: (int){ 435 } 435: (int){ 436 } 436: (int){ 437 } 437: (int){ 438 } 438: (int){ 439 } 439: (int){ 440 } 440: (int){ 441 } 441: (int){ 442 } 442: (int){ 443 } 443: (int){ 444 } 444: (int){ 445 } 445: (int){ 446 } 446: (int){ 447 } 447: (int){ 448 } 448: (int){ 449 } 449: (int){ 450 } 450: (int){ 451 } 451: (int){ 452 } 452: (int){ 453 } 453: (int){ 454 } 454: (int){ 455 } 455: (int){ 456 } 456: (int){ 457 } 457: (int){ 458 } 458: (int){ 459 } 459: (int){ 460 } 460: (int){ 461 } 461: (int){ 462 } 462: (int){ 463 } 463: (int){ 464 } 464: (int){ 465 } 465: (int){ 466 } 466: (int){ 467 } 467: (int){ 468 } 468: (int){ 469 } 469: (int){ 470 } 470: (int){ 471 } 471: (int){ 472 } 472: (int){ 473 } 473: (int){ 474 } 474: (int){ 475 } 475: (int){ 476 } 476: (int){ 477 } 477: (int){ 478 } 478: (int){ 479 } 479: (int){ 480 } 480: (int){ 481 } 481: (int){ 482 } 482: (int){ 483 } 483: (int){ 484 } 484: (int){ 485 } 485: (int){ 486 } 486: (int){ 487 } 487: (int){ 488 } 488: (int){ 489 } 489: (int){ 490 } 490: (int){ 491 } 491: (int){ 492 } 492: (int){ 493 } 493: (int){ 494 } 494: (int){ 495 } 495: (int){ 496 } 496: (int){ 497 } 497: (int){ 498 } 498: (int){ 499 } 499: (int){ 500 } 500: (int){ 501 } 501: (int){ 502 } 502: (int){ 503 } 503: (int){ 504 } 504: (int){ 505 } 505: (int){ 506 } 506: (int){ 507 } 507: (int){ 508 } 508: (int){ 509 } 509: (int){ 510 } 510: (int){ 511 } 511: (int){ 512 } 512: (int){ 513 } 513: (int){ 514 } 514: (int){ 515 } 515: (int){ 516 } 516: (int){ 517 } 517: (int){ 518 } 518: (int){ 519 } 519: (int){ 520 } 520: (int){ 521 } 521: (int){ 522 } 522: (int){ 523 } 523: (int){ 524 } 524: (int){ 525 } 525: (int){ 526 } 526: (int){ 527 } 527: (int){ 528 } 528: (int){ 529 } 529: (int){ 530 } 530: (int){ 531 } 531: (int){ 532 } 532: (int){ 533 } 533: (int){ 534 } 534: (int){ 535 } 535: (int){ 536 } 536: (int){ 537 } 537: (int){ 538 } 538: (int){ 539 } 539: (int){ 540 } 540: (int){ 541 } 541: (int){ 542 } 542: (int){ 543 } 543: (int){ 544 } 544: (int){ 545 } 545: (int){ 546 } 546: (int){ 547 } 547: (int){ 548 } 548: (int){ 549 } 549: (int){ 550 } 550: (int){ 551 } 551: (int){ 552 } 552: (int){ 553 } 553: (int){ 554 } 554: (int){ 555 } 555: (int){ 556 } 556: (int){ 557 } 557: (int){ 558 } 558: (int){ 559 } 559: (int){ 560 } 560: (int){ 561 } 561: (int){ 562 } 562: (int){ 563 } 563: (int){ 564 } 564: (int){ 565 } 565: (int){ 566 } 566: (int){ 567 } 567: (int){ 568 } 568: (int){ 569 } 569: (int){ 570 } 570: (int){ 571 } 571: (int){ 572 } 572: (int){ 573 } 573: (int){ 574 } 574: (int){ 575 } 575: (int){ 576 } 576: (int){ 577 } 577: (int){ 578 } 578: (int){ 579 } 579: (int){ 580 } 580: (int){ 581 } 581: (int){ 582 } 582: (int){ 583 } 583: (int){ 584 } 584: (int){ 585 } 585: (int){ 586 } 586: (int){ 587 } 587: (int){ 588 } 588: (int){ 589 } 589: (int){ 590 } 590: (int){ 591 } 591: (int){ 592 } 592: (int){ 593 } 593: (int){ 594 } 594: (int){ 595 } 595: (int){ 596 } 596: (int){ 597 } 597: (int){ 598 } 598: (int){ 599 } 599: (int){ 600 } 600: (int){ 601 } 601: (int){ 602 } 602: (int){ 603 } 603: (int){ 604 } 604: (int){ 605 } 605: (int){ 606 } 606: (int){ 607 } 607: (int){ 608 } 608: (int){ 609 } 609: (int){ 610 } 610: (int){ 611 } 611: (int){ 612 } 612: (int){ 613 } 613: (int){ 614 } 614: (int){ 615 } 615: (int){ 616 } 616: (int){ 617 } 617: (int){ 618 } 618: (int){ 619 } 619: (int){ 620 } 620: (int){ 621 } 621: (int){ 622 } 622: (int){ 623 } 623: (int){ 624 } 624: (int){ 625 } 625: (int){ 626 } 626: (int){ 627 } 627: (int){ 628 } 628: (int){ 629 } 629: (int){ 630 } 630: (int){ 631 } 631: (int){ 632 } 632: (int){ 633 } 633: (int){ 634 } 634: (int){ 635 } 635: (int){ 636 } 636: (int){ 637 } 637: (int){ 638 } 638: (int){ 639 } 639: (int){ 640 } 640: (int){ 641 } 641: (int){ 642 } 642: (int){ 643 } 643: (int){ 644 } 644: (int){ 645 } 645: (int){ 646 } 646: (int){ 647 } 647: (int){ 648 } 648: (int){ 649 } 649: (int){ 650 } 650: (int){ 651 } 651: (int){ 652 } 652: (int){ 653 } 653: (int){ 654 } 654: (int){ 655 } 655: (int){ 656 } 656: (int){ 657 } 657: (int){ 658 } 658: (int){ 659 } 659: (int){ 660 } 660: (int){ 661 } 661: (int){ 662 } 662: (int){ 663 } 663: (int){ 664 } 664: (int){ 665 } 665: (int){ 666 } 666: (int){ 667 } 667: (int){ 668 } 668: (int){ 669 } 669: (int){ 670 } 670: (int){ 671 } 671: (int){ 672 } 672: (int){ 673 } 673: (int){ 674 } 674: (int){ 675 } 675: (int){ 676 } 676: (int){ 677 } 677: (int){ 678 } 678: (int){ 679 } 679: (int){ 680 } 680: (int){ 681 } 681: (int){ 682 } 682: (int){ 683 } 683: (int){ 684 } 684: (int){ 685 } 685: (int){ 686 } 686: (int){ 687 } 687: (int){ 688 } 688: (int){ 689 } 689: (int){ 690 } 690: (int){ 691 } 691: (int){ 692 } 692: (int){ 693 } 693: (int){ 694 } 694: (int){ 695 } 695: (int){ 696 } 696: (int){ 697 } 697: (int){ 698 } 698: (int){ 699 } 699: (int){ 700 } 700: (int){ 701 } 701: (int){ 702 } 702: (int){ 703 } 703: (int){ 704 } 704: (int){ 705 } 705: (int){ 706 } 706: (int){ 707 } 707: (int){ 708 } 708: (int){ 709 } 709: (int){ 710 } 710: (int){ 711 } 711: (int){ 712 } 712: (int){ 713 } 713: (int){ 714 } 714: (int){ 715 } 715: (int){ 716 } 716: (int){ 717 } 717: (int){ 718 } 718: (int){ 719 } 719: (int){ 720 } 720: (int){ 721 } 721: (int){ 722 } 722: (int){ 723 } 723: (int){ 724 } 724: (int){ 725 } 725: (int){ 726 } 726: (int){ 727 } 727: (int){ 728 } 728: (int){ 729 } 729: (int){ 730 } 730: (int){ 731 } 731: (int){ 732 } 732: (int){ 733 } 733: (int){ 734 } 734: (int){ 735 } 735: (int){ 736 } 736: (int){ 737 } 737: (int){ 738 } 738: (int){ 739 } 739: (int){ 740 } 740: (int){ 741 } 741: (int){ 742 } 742: (int){ 743 } 743: (int){ 744 } 744: (int){ 745 } 745: (int){ 746 } 746: (int){ 747 } 747: (int){ 748 } 748: (int){ 749 } 749: (int){ 750 } 750: (int){ 751 } 751: (int){ 752 } 752: (int){ 753 } 753: (int){ 754 } 754: (int){ 755 } 755: (int){ 756 } 756: (int){ 757 } 757: (int){ 758 } 758: (int){ 759 } 759: (int){ 760 } 760: (int){ 761 } 761: (int){ 762 } 762: (int){ 763 } 763: (int){ 764 } 764: (int){ 765 } 765: (int){ 766 } 766: (int){ 767 } 767: (int){ 768 } 768: (int){ 769 } 769: (int){ 770 } 770: (int){ 771 } 771: (int){ 772 } 772: (int){ 773 } 773: (int){ 774 } 774: (int){ 775 } 775: (int){ 776 } 776: (int){ 777 } 777: (int){ 778 } 778: (int){ 779 } 779: (int){ 780 } 780: (int){ 781 } 781: (int){ 782 } 782: (int){ 783 } 783: (int){ 784 } 784: (int){ 785 } 785: (int){ 786 } 786: (int){ 787 } 787: (int){ 788 } 788: (int){ 789 } 789: (int){ 790 } 790: (int){ 791 } 791: (int){ 792 } 792: (int){ 793 } 793: (int){ 794 } 794: (int){ 795 } 795: (int){ 796 } 796: (int){ 797 } 797: (int){ 798 } 798: (int){ 799 } 799: (int){ 800 } 800: (int){ 801 } 801: (int){ 802 } 802: (int){ 803 } 803: (int){ 804 } 804: (int){ 805 } 805: (int){ 806 } 806: (int){ 807 } 807: (int){ 808 } 808: (int){ 809 } 809: (int){ 810 } 810: (int){ 811 } 811: (int){ 812 } 812: (int){ 813 } 813: (int){ 814 } 814: (int){ 815 } 815: (int){ 816 } 816: (int){ 817 } 817: (int){ 818 } 818: (int){ 819 } 819: (int){ 820 } 820: (int){ 821 } 821: (int){ 822 } 822: (int){ 823 } 823: (int){ 824 } 824: (int){ 825 } 825: (int){ 826 } 826: (int){ 827 } 827: (int){ 828 } 828: (int){ 829 } 829: (int){ 830 } 830: (int){ 831 } 831: (int){ 832 } 832: (int){ 833 } 833: (int){ 834 } 834: (int){ 835 } 835: (int){ 836 } 836: (int){ 837 } 837: (int){ 838 } 838: (int){ 839 } 839: (int){ 840 } 840: (int){ 841 } 841: (int){ 842 } 842: (int){ 843 } 843: (int){ 844 } 844: (int){ 845 } 845: (int){ 846 } 846: (int){ 847 } 847: (int){ 848 } 848: (int){ 849 } 849: (int){ 850 } 850: (int){ 851 } 851: (int){ 852 } 852: (int){ 853 } 853: (int){ 854 } 854: (int){ 855 } 855: (int){ 856 } 856: (int){ 857 } 857: (int){ 858 } 858: (int){ 859 } 859: (int){ 860 } 860: (int){ 861 } 861: (int){ 862 } 862: (int){ 863 } 863: (int){ 864 } 864: (int){ 865 } 865: (int){ 866 } 866: (int){ 867 } 867: (int){ 868 } 868: (int){ 869 } 869: (int){ 870 } 870: (int){ 871 } 871: (int){ 872 } 872: (int){ 873 } 873: (int){ 874 } 874: (int){ 875 } 875: (int){ 876 } 876: (int){ 877 } 877: (int){ 878 } 878: (int){ 879 } 879: (int){ 880 } 880: (int){ 881 } 881: (int){ 882 } 882: (int){ 883 } 883: (int){ 884 } 884: (int){ 885 } 885: (int){ 886 } 886: (int){ 887 } 887: (int){ 888 } 888: (int){ 889 } 889: (int){ 890 } 890: (int){ 891 } 891: (int){ 892 } 892: (int){ 893 } 893: (int){ 894 } 894: (int){ 895 } 895: (int){ 896 } 896: (int){ 897 } 897: (int){ 898 } 898: (int){ 899 } 899: (int){ 900 } 900: (int){ 901 } 901: (int){ 902 } 902: (int){ 903 } 903: (int){ 904 } 904: (int){ 905 } 905: (int){ 906 } 906: (int){ 907 } 907: (int){ 908 } 908: (int){ 909 } 909: (int){ 910 } 910: (int){ 911 } 911: (int){ 912 } 912: (int){ 913 } 913: (int){ 914 } 914: (int){ 915 } 915: (int){ 916 } 916: (int){ 917 } 917: (int){ 918 } 918: (int){ 919 } 919: (int){ 920 } 920: (int){ 921 } 921: (int){ 922 } 922: (int){ 923 } 923: (int){ 924 } 924: (int){ 925 } 925: (int){ 926 } 926: (int){ 927 } 927: (int){ 928 } 928: (int){ 929 } 929: (int){ 930 } 930: (int){ 931 } 931: (int){ 932 } 932: (int){ 933 } 933: (int){ 934 } 934: (int){ 935 } 935: (int){ 936 } 936: (int){ 937 } 937: (int){ 938 } 938: (int){ 939 } 939: (int){ 940 } 940: (int){ 941 } 941: (int){ 942 } 942: (int){ 943 } 943: (int){ 944 } 944: (int){ 945 } 945: (int){ 946 } 946: (int){ 947 } 947: (int){ 948 } 948: (int){ 949 } 949: (int){ 950 } 950: (int){ 951 } 951: (int){ 952 } 952: (int){ 953 } 953: (int){ 954 } 954: (int){ 955 } 955: (int){ 956 } 956: (int){ 957 } 957: (int){ 958 } 958: (int){ 959 } 959: (int){ 960 } 960: (int){ 961 } 961: (int){ 962 } 962: (int){ 963 } 963: (int){ 964 } 964: (int){ 965 } 965: (int){ 966 } 966: (int){ 967 } 967: (int){ 968 } 968: (int){ 969 } 969: (int){ 970 } 970: (int){ 971 } 971: (int){ 972 } 972: (int){ 973 } 973: (int){ 974 } 974: (int){ 975 } 975: (int){ 976 } 976: (int){ 977 } 977: (int){ 978 } 978: (int){ 979 } 979: (int){ 980 } 980: (int){ 981 } 981: (int){ 982 } 982: (int){ 983 } 983: (int){ 984 } 984: (int){ 985 } 985: (int){ 986 } 986: (int){ 987 } 987: (int){ 988 } 988: (int){ 989 } 989: (int){ 990 } 990: (int){ 991 } 991: (int){ 992 } 992: (int){ 993 } 993: (int){ 994 } 994: (int){ 995 } 995: (int){ 996 } 996: (int){ 997 } 997: (int){ 998 } 998: (int){ 999 } 999: (int){ 1000 } 1000: (int){ 1001 } 1001: (int){ 1002 } 1002: (int){ 1003 } 1003: (int){ 1004 } 1004: (int){ 1005 } 1005: (int){ 1006 } 1006: (int){ 1007 } 1007: (int){ 1008 } 1008: (int){ 1009 } 1009: (int){ 1010 } 1010: (int){ 1011 } 1011: (int){ 1012 } 1012: (int){ 1013 } 1013: (int){ 1014 } 1014: (int){ 1015 } 1015: (int){ 1016 } 1016: (int){ 1017 } 1017: (int){ 1018 } 1018: (int){ 1019 } 1019: (int){ 1020 } 1020: (int){ 1021 } 1021: (int){ 1022 } 1022: (int){ 1023 } 1023: (int){ 1024 } 1024: (int){ 1025 } 1025: (int){ 1026 } 1026: (int){ 1027 } 1027: (int){ 1028 } 1028: (int){ 1029 } 1029: (int){ 1030 } 1030: (int){ 1031 } 1031: (int){ 1032 } 1032: (int){ 1033 } 1033: (int){ 1034 } 1034: (int){ 1035 } 1035: (int){ 1036 } 1036: (int){ 1037 } 1037: (int){ 1038 } 1038: (int){ 1039 } 1039: (int){ 1040 } 1040: (int){ 1041 } 1041: (int){ 1042 } 1042: (int){ 1043 } 1043: (int){ 1044 } 1044: (int){ 1045 } 1045: (int){ 1046 } 1046: (int){ 1047 } 1047: (int){ 1048 } 1048: (int){ 1049 } 1049: (int){ 1050 } 1050: (int){ 1051 } 1051: (int){ 1052 } 1052: (int){ 1053 } 1053: (int){ 1054 } 1054: (int){ 1055 } 1055: (int){ 1056 } 1056: (int){ 1057 } 1057: (int){ 1058 } 1058: (int){ 1059 } 1059: (int){ 1060 } 1060: (int){ 1061 } 1061: (int){ 1062 } 1062: (int){ 1063 } 1063: (int){ 1064 } 1064: (int){ 1065 } 1065: (int){ 1066 } 1066: (int){ 1067 } 1067: (int){ 1068 } 1068: (int){ 1069 } 1069: (int){ 1070 } 1070: (int){ 1071 } 1071: (int){ 1072 } 1072: (int){ 1073 } 1073: (int){ 1074 } 1074: (int){ 1075 } 1075: (int){ 1076 } 1076: (int){ 1077 } 1077: (int){ 1078 } 1078: (int){ 1079 } 1079: (int){ 1080 } 1080: (int){ 1081 } 1081: (int){ 1082 } 1082: (int){ 1083 } 1083: (int){ 1084 } 1084: (int){ 1085 } 1085: (int){ 1086 } 1086: (int){ 1087 } 1087: (int){ 1088 } 1088: (int){ 1089 } 1089: (int){ 1090 } 1090: (int){ 1091 } 1091: (int){ 1092 } 1092: (int){ 1093 } 1093: (int){ 1094 } 1094: (int){ 1095 } 1095: (int){ 1096 } 1096: (int){ 1097 } 1097: (int){ 1098 } 1098: (int){ 1099 } 1099: (int){ 1100 } 1100: (int){ 1101 } 1101: (int){ 1102 } 1102: (int){ 1103 } 1103: (int){ 1104 } 1104: (int){ 1105 } 1105: (int){ 1106 } 1106: (int){ 1107 } 1107: (int){ 1108 } 1108: (int){ 1109 } 1109: (int){ 1110 } 1110: (int){ 1111 } 1111: (int){ 1112 } 1112: (int){ 1113 } 1113: (int){ 1114 } 1114: (int){ 1115 } 1115: (int){ 1116 } 1116: (int){ 1117 } 1117: (int){ 1118 } 1118: (int){ 1119 } 1119: (int){ 1120 } 1120: (int){ 1121 } 1121: (int){ 1122 } 1122: (int){ 1123 } 1123: (int){ 1124 } 1124: (int){ 1125 } 1125: (int){ 1126 } 1126: (int){ 1127 } 1127: (int){ 1128 } 1128: (int){ 1129 } 1129: (int){ 1130 } 1130: (int){ 1131 } 1131: (int){ 1132 } 1132: (int){ 1133 } 1133: (int){ 1134 } 1134: (int){ 1135 } 1135: (int){ 1136 } 1136: (int){ 1137 } 1137: (int){ 1138 } 1138: (int){ 1139 } 1139: (int){ 1140 } 1140: (int){ 1141 } 1141: (int){ 1142 } 1142: (int){ 1143 } 1143: (int){ 1144 } 1144: (int){ 1145 } 1145: (int){ 1146 } 1146: (int){ 1147 } 1147: (int){ 1148 } 1148: (int){ 1149 } 1149: (int){ 1150 } 1150: (int){ 1151 } 1151: (int){ 1152 } 1152: (int){ 1153 } 1153: (int){ 1154 } 1154: (int){ 1155 } 1155: (int){ 1156 } 1156: (int){ 1157 } 1157: (int){ 1158 } 1158: (int){ 1159 } 1159: (int){ 1160 } 1160: (int){ 1161 } 1161: (int){ 1162 } 1162: (int){ 1163 } 1163: (int){ 1164 } 1164: (int){ 1165 } 1165: (int){ 1166 } 1166: (int){ 1167 } 1167: (int){ 1168 } 1168: (int){ 1169 } 1169: (int){ 1170 } 1170: (int){ 1171 } 1171: (int){ 1172 } 1172: (int){ 1173 } 1173: (int){ 1174 } 1174: (int){ 1175 } 1175: (int){ 1176 } 1176: (int){ 1177 } 1177: (int){ 1178 } 1178: (int){ 1179 } 1179: (int){ 1180 } 1180: (int){ 1181 } 1181: (int){ 1182 } 1182: (int){ 1183 } 1183: (int){ 1184 } 1184: (int){ 1185 } 1185: (int){ 1186 } 1186: (int){ 1187 } 1187: (int){ 1188 } 1188: (int){ 1189 } 1189: (int){ 1190 } 1190: (int){ 1191 } 1191: (int){ 1192 } 1192: (int){ 1193 } 1193: (int){ 1194 } 1194: (int){ 1195 } 1195: (int){ 1196 } 1196: (int){ 1197 } 1197: (int){ 1198 } 1198: (int){ 1199 } 1199: (int){ 1200 } 1200: (int){ 1201 } 1201: (int){ 1202 } 1202: (int){ 1203 } 1203: (int){ 1204 } 1204: (int){ 1205 } 1205: (int){ 1206 } 1206: (int){ 1207 } 1207: (int){ 1208 } 1208: (int){ 1209 } 1209: (int){ 1210 } 1210: (int){ 1211 } 1211: (int){ 1212 } 1212: (int){ 1213 } 1213: (int){ 1214 } 1214: (int){ 1215 } 1215: (int){ 1216 } 1216: (int){ 1217 } 1217: (int){ 1218 } 1218: (int){ 1219 } 1219: (int){ 1220 } 1220: (int){ 1221 } 1221: (int){ 1222 } 1222: (int){ 1223 } 1223: (int){ 1224 } 1224: (int){ 1225 } 1225: (int){ 1226 } 1226: (int){ 1227 } 1227: (int){ 1228 } 1228: (int){ 1229 } 1229: (int){ 1230 } 1230: (int){ 1231 } 1231: (int){ 1232 } 1232: (int){ 1233 } 1233: (int){ 1234 } 1234: (int){ 1235 } 1235: (int){ 1236 } 1236: (int){ 1237 } 1237: (int){ 1238 } 1238: (int){ 1239 } 1239: (int){ 1240 } 1240: (int){ 1241 } 1241: (int){ 1242 } 1242: (int){ 1243 } 1243: (int){ 1244 } 1244: (int){ 1245 } 1245: (int){ 1246 } 1246: (int){ 1247 } 1247: (int){ 1248 } 1248: (int){ 1249 } 1249: (int){ 1250 } 1250: (int){ 1251 } 1251: (int){ 1252 } 1252: (int){ 1253 } 1253: (int){ 1254 } 1254: (int){ 1255 } 1255: (int){ 1256 } 1256: (int){ 1257 } 1257: (int){ 1258 } 1258: (int){ 1259 } 1259: (int){ 1260 } 1260: (int){ 1261 } 1261: (int){ 1262 } 1262: (int){ 1263 } 1263: (int){ 1264 } 1264: (int){ 1265 } 1265: (int){ 1266 } 1266: (int){ 1267 } 1267: (int){ 1268 } 1268: (int){ 1269 } 1269: (int){ 1270 } 1270: (int){ 1271 } 1271: (int){ 1272 } 1272: (int){ 1273 } 1273: (int){ 1274 } 1274: (int){ 1275 } 1275: (int){ 1276 } 1276: (int){ 1277 } 1277: (int){ 1278 } 1278: (int){ 1279 } 1279: (int){ 1280 } 1280: (int){ 1281 } 1281: (int){ 1282 } 1282: (int){ 1283 } 1283: (int){ 1284 } 1284: (int){ 1285 } 1285: (int){ 1286 } 1286: (int){ 1287 } 1287: (int){ 1288 } 1288: (int){ 1289 } 1289: (int){ 1290 } 1290: (int){ 1291 } 1291: (int){ 1292 } 1292: (int){ 1293 } 1293: (int){ 1294 } 1294: (int){ 1295 } 1295: (int){ 1296 } 1296: (int){ 1297 } 1297: (int){ 1298 } 1298: (int){ 1299 } 1299: (int){ 1300 } 1300: (int){ 1301 } 1301: (int){ 1302 } 1302: (int){ 1303 } 1303: (int){ 1304 } 1304: (int){ 1305 } 1305: (int){ 1306 } 1306: (int){ 1307 } 1307: (int){ 1308 } 1308: (int){ 1309 } 1309: (int){ 1310 } 1310: (int){ 1311 } 1311: (int){ 1312 } 1312: (int){ 1313 } 1313: (int){ 1314 } 1314: (int){ 1315 } 1315: (int){ 1316 } 1316: (int){ 1317 } 1317: (int){ 1318 } 1318: (int){ 1319 } 1319: (int){ 1320 } 1320: (int){ 1321 } 1321: (int){ 1322 } 1322: (int){ 1323 } 1323: (int){ 1324 } 1324: (int){ 1325 } 1325: (int){ 1326 } 1326: (int){ 1327 } 1327: (int){ 1328 } 1328: (int){ 1329 } 1329: (int){ 1330 } 1330: (int){ 1331 } 1331: (int){ 1332 } 1332: (int){ 1333 } 1333: (int){ 1334 } 1334: (int){ 1335 } 1335: (int){ 1336 } 1336: (int){ 1337 } 1337: (int){ 1338 } 1338: (int){ 1339 } 1339: (int){ 1340 } 1340: (int){ 1341 } 1341: (int){ 1342 } 1342: (int){ 1343 } 1343: (int){ 1344 } 1344: (int){ 1345 } 1345: (int){ 1346 } 1346: (int){ 1347 } 1347: (int){ 1348 } 1348: (int){ 1349 } 1349: (int){ 1350 } 1350: (int){ 1351 } 1351: (int){ 1352 } 1352: (int){ 1353 } 1353: (int){ 1354 } 1354: (int){ 1355 } 1355: (int){ 1356 } 1356: (int){ 1357 } 1357: (int){ 1358 } 1358: (int){ 1359 } 1359: (int){ 1360 } 1360: (int){ 1361 } 1361: (int){ 1362 } 1362: (int){ 1363 } 1363: (int){ 1364 } 1364: (int){ 1365 } 1365: (int){ 1366 } 1366: (int){ 1367 } 1367: (int){ 1368 } 1368: (int){ 1369 } 1369: (int){ 1370 } 1370: (int){ 1371 } 1371: (int){ 1372 } 1372: (int){ 1373 } 1373: (int){ 1374 } 1374: (int){ 1375 } 1375: (int){ 1376 } 1376: (int){ 1377 } 1377: (int){ 1378 } 1378: (int){ 1379 } 1379: (int){ 1380 } 1380: (int){ 1381 } 1381: (int){ 1382 } 1382: (int){ 1383 } 1383: (int){ 1384 } 1384: (int){ 1385 } 1385: (int){ 1386 } 1386: (int){ 1387 } 1387: (int){ 1388 } 1388: (int){ 1389 } 1389: (int){ 1390 } 1390: (int){ 1391 } 1391: (int){ 1392 } 1392: (int){ 1393 } 1393: (int){ 1394 } 1394: (int){ 1395 } 1395: (int){ 1396 } 1396: (int){ 1397 } 1397: (int){ 1398 } 1398: (int){ 1399 } 1399: (int){ 1400 } 1400: (int){ 1401 } 1401: (int){ 1402 } 1402: (int){ 1403 } 1403: (int){ 1404 } 1404: (int){ 1405 } 1405: (int){ 1406 } 1406: (int){ 1407 } 1407: (int){ 1408 } 1408: (int){ 1409 } 1409: (int){ 1410 } 1410: (int){ 1411 } 1411: (int){ 1412 } 1412: (int){ 1413 } 1413: (int){ 1414 } 1414: (int){ 1415 } 1415: (int){ 1416 } 1416: (int){ 1417 } 1417: (int){ 1418 } 1418: (int){ 1419 } 1419: (int){ 1420 } 1420: (int){ 1421 } 1421: (int){ 1422 } 1422: (int){ 1423 } 1423: (int){ 1424 } 1424: (int){ 1425 } 1425: (int){ 1426 } 1426: (int){ 1427 } 1427: (int){ 1428 } 1428: (int){ 1429 } 1429: (int){ 1430 } 1430: (int){ 1431 } 1431: (int){ 1432 } 1432: (int){ 1433 } 1433: (int){ 1434 } 1434: (int){ 1435 } 1435: (int){ 1436 } 1436: (int){ 1437 } 1437: (int){ 1438 } 1438: (int){ 1439 } 1439: (int){ 1440 } 1440: (int){ 1441 } 1441: (int){ 1442 } 1442: (int){ 1443 } 1443: (int){ 1444 } 1444: (int){ 1445 } 1445: (int){ 1446 } 1446: (int){ 1447 } 1447: (int){ 1448 } 1448: (int){ 1449 } 1449: (int){ 1450 } 1450: (int){ 1451 } 1451: (int){ 1452 } 1452: (int){ 1453 } 1453: (int){ 1454 } 1454: (int){ 1455 } 1455: (int){ 1456 } 1456: (int){ 1457 } 1457: (int){ 1458 } 1458: (int){ 1459 } 1459: (int){ 1460 } 1460: (int){ 1461 } 1461: (int){ 1462 } 1462: (int){ 1463 } 1463: (int){ 1464 } 1464: (int){ 1465 } 1465: (int){ 1466 } 1466: (int){ 1467 } 1467: (int){ 1468 } 1468: (int){ 1469 } 1469: (int){ 1470 } 1470: (int){ 1471 } 1471: (int){ 1472 } 1472: (int){ 1473 } 1473: (int){ 1474 } 1474: (int){ 1475 } 1475: (int){ 1476 } 1476: (int){ 1477 } 1477: (int){ 1478 } 1478: (int){ 1479 } 1479: (int){ 1480 } 1480: (int){ 1481 } 1481: (int){ 1482 } 1482: (int){ 1483 } 1483: (int){ 1484 } 1484: (int){ 1485 } 1485: (int){ 1486 } 1486: (int){ 1487 } 1487: (int){ 1488 } 1488: (int){ 1489 } 1489: (int){ 1490 } 1490: (int){ 1491 } 1491: (int){ 1492 } 1492: (int){ 1493 } 1493: (int){ 1494 } 1494: (int){ 1495 } 1495: (int){ 1496 } 1496: (int){ 1497 } 1497: (int){ 1498 } 1498: (int){ 1499 } } unified: (struct){ "1": (bool){ true } "2": (bool){ true } "3": (bool){ true } "4": (bool){ true } "5": (bool){ true } "6": (bool){ true } "7": (bool){ true } "8": (bool){ true } "9": (bool){ true } "10": (bool){ true } "11": (bool){ true } "12": (bool){ true } "13": (bool){ true } "14": (bool){ true } "15": (bool){ true } "16": (bool){ true } "17": (bool){ true } "18": (bool){ true } "19": (bool){ true } "20": (bool){ true } "21": (bool){ true } "22": (bool){ true } "23": (bool){ true } "24": (bool){ true } "25": (bool){ true } "26": (bool){ true } "27": (bool){ true } "28": (bool){ true } "29": (bool){ true } "30": (bool){ true } "31": (bool){ true } "32": (bool){ true } "33": (bool){ true } "34": (bool){ true } "35": (bool){ true } "36": (bool){ true } "37": (bool){ true } "38": (bool){ true } "39": (bool){ true } "40": (bool){ true } "41": (bool){ true } "42": (bool){ true } "43": (bool){ true } "44": (bool){ true } "45": (bool){ true } "46": (bool){ true } "47": (bool){ true } "48": (bool){ true } "49": (bool){ true } "50": (bool){ true } "51": (bool){ true } "52": (bool){ true } "53": (bool){ true } "54": (bool){ true } "55": (bool){ true } "56": (bool){ true } "57": (bool){ true } "58": (bool){ true } "59": (bool){ true } "60": (bool){ true } "61": (bool){ true } "62": (bool){ true } "63": (bool){ true } "64": (bool){ true } "65": (bool){ true } "66": (bool){ true } "67": (bool){ true } "68": (bool){ true } "69": (bool){ true } "70": (bool){ true } "71": (bool){ true } "72": (bool){ true } "73": (bool){ true } "74": (bool){ true } "75": (bool){ true } "76": (bool){ true } "77": (bool){ true } "78": (bool){ true } "79": (bool){ true } "80": (bool){ true } "81": (bool){ true } "82": (bool){ true } "83": (bool){ true } "84": (bool){ true } "85": (bool){ true } "86": (bool){ true } "87": (bool){ true } "88": (bool){ true } "89": (bool){ true } "90": (bool){ true } "91": (bool){ true } "92": (bool){ true } "93": (bool){ true } "94": (bool){ true } "95": (bool){ true } "96": (bool){ true } "97": (bool){ true } "98": (bool){ true } "99": (bool){ true } "100": (bool){ true } "101": (bool){ true } "102": (bool){ true } "103": (bool){ true } "104": (bool){ true } "105": (bool){ true } "106": (bool){ true } "107": (bool){ true } "108": (bool){ true } "109": (bool){ true } "110": (bool){ true } "111": (bool){ true } "112": (bool){ true } "113": (bool){ true } "114": (bool){ true } "115": (bool){ true } "116": (bool){ true } "117": (bool){ true } "118": (bool){ true } "119": (bool){ true } "120": (bool){ true } "121": (bool){ true } "122": (bool){ true } "123": (bool){ true } "124": (bool){ true } "125": (bool){ true } "126": (bool){ true } "127": (bool){ true } "128": (bool){ true } "129": (bool){ true } "130": (bool){ true } "131": (bool){ true } "132": (bool){ true } "133": (bool){ true } "134": (bool){ true } "135": (bool){ true } "136": (bool){ true } "137": (bool){ true } "138": (bool){ true } "139": (bool){ true } "140": (bool){ true } "141": (bool){ true } "142": (bool){ true } "143": (bool){ true } "144": (bool){ true } "145": (bool){ true } "146": (bool){ true } "147": (bool){ true } "148": (bool){ true } "149": (bool){ true } "150": (bool){ true } "151": (bool){ true } "152": (bool){ true } "153": (bool){ true } "154": (bool){ true } "155": (bool){ true } "156": (bool){ true } "157": (bool){ true } "158": (bool){ true } "159": (bool){ true } "160": (bool){ true } "161": (bool){ true } "162": (bool){ true } "163": (bool){ true } "164": (bool){ true } "165": (bool){ true } "166": (bool){ true } "167": (bool){ true } "168": (bool){ true } "169": (bool){ true } "170": (bool){ true } "171": (bool){ true } "172": (bool){ true } "173": (bool){ true } "174": (bool){ true } "175": (bool){ true } "176": (bool){ true } "177": (bool){ true } "178": (bool){ true } "179": (bool){ true } "180": (bool){ true } "181": (bool){ true } "182": (bool){ true } "183": (bool){ true } "184": (bool){ true } "185": (bool){ true } "186": (bool){ true } "187": (bool){ true } "188": (bool){ true } "189": (bool){ true } "190": (bool){ true } "191": (bool){ true } "192": (bool){ true } "193": (bool){ true } "194": (bool){ true } "195": (bool){ true } "196": (bool){ true } "197": (bool){ true } "198": (bool){ true } "199": (bool){ true } "200": (bool){ true } "201": (bool){ true } "202": (bool){ true } "203": (bool){ true } "204": (bool){ true } "205": (bool){ true } "206": (bool){ true } "207": (bool){ true } "208": (bool){ true } "209": (bool){ true } "210": (bool){ true } "211": (bool){ true } "212": (bool){ true } "213": (bool){ true } "214": (bool){ true } "215": (bool){ true } "216": (bool){ true } "217": (bool){ true } "218": (bool){ true } "219": (bool){ true } "220": (bool){ true } "221": (bool){ true } "222": (bool){ true } "223": (bool){ true } "224": (bool){ true } "225": (bool){ true } "226": (bool){ true } "227": (bool){ true } "228": (bool){ true } "229": (bool){ true } "230": (bool){ true } "231": (bool){ true } "232": (bool){ true } "233": (bool){ true } "234": (bool){ true } "235": (bool){ true } "236": (bool){ true } "237": (bool){ true } "238": (bool){ true } "239": (bool){ true } "240": (bool){ true } "241": (bool){ true } "242": (bool){ true } "243": (bool){ true } "244": (bool){ true } "245": (bool){ true } "246": (bool){ true } "247": (bool){ true } "248": (bool){ true } "249": (bool){ true } "250": (bool){ true } "251": (bool){ true } "252": (bool){ true } "253": (bool){ true } "254": (bool){ true } "255": (bool){ true } "256": (bool){ true } "257": (bool){ true } "258": (bool){ true } "259": (bool){ true } "260": (bool){ true } "261": (bool){ true } "262": (bool){ true } "263": (bool){ true } "264": (bool){ true } "265": (bool){ true } "266": (bool){ true } "267": (bool){ true } "268": (bool){ true } "269": (bool){ true } "270": (bool){ true } "271": (bool){ true } "272": (bool){ true } "273": (bool){ true } "274": (bool){ true } "275": (bool){ true } "276": (bool){ true } "277": (bool){ true } "278": (bool){ true } "279": (bool){ true } "280": (bool){ true } "281": (bool){ true } "282": (bool){ true } "283": (bool){ true } "284": (bool){ true } "285": (bool){ true } "286": (bool){ true } "287": (bool){ true } "288": (bool){ true } "289": (bool){ true } "290": (bool){ true } "291": (bool){ true } "292": (bool){ true } "293": (bool){ true } "294": (bool){ true } "295": (bool){ true } "296": (bool){ true } "297": (bool){ true } "298": (bool){ true } "299": (bool){ true } "300": (bool){ true } "301": (bool){ true } "302": (bool){ true } "303": (bool){ true } "304": (bool){ true } "305": (bool){ true } "306": (bool){ true } "307": (bool){ true } "308": (bool){ true } "309": (bool){ true } "310": (bool){ true } "311": (bool){ true } "312": (bool){ true } "313": (bool){ true } "314": (bool){ true } "315": (bool){ true } "316": (bool){ true } "317": (bool){ true } "318": (bool){ true } "319": (bool){ true } "320": (bool){ true } "321": (bool){ true } "322": (bool){ true } "323": (bool){ true } "324": (bool){ true } "325": (bool){ true } "326": (bool){ true } "327": (bool){ true } "328": (bool){ true } "329": (bool){ true } "330": (bool){ true } "331": (bool){ true } "332": (bool){ true } "333": (bool){ true } "334": (bool){ true } "335": (bool){ true } "336": (bool){ true } "337": (bool){ true } "338": (bool){ true } "339": (bool){ true } "340": (bool){ true } "341": (bool){ true } "342": (bool){ true } "343": (bool){ true } "344": (bool){ true } "345": (bool){ true } "346": (bool){ true } "347": (bool){ true } "348": (bool){ true } "349": (bool){ true } "350": (bool){ true } "351": (bool){ true } "352": (bool){ true } "353": (bool){ true } "354": (bool){ true } "355": (bool){ true } "356": (bool){ true } "357": (bool){ true } "358": (bool){ true } "359": (bool){ true } "360": (bool){ true } "361": (bool){ true } "362": (bool){ true } "363": (bool){ true } "364": (bool){ true } "365": (bool){ true } "366": (bool){ true } "367": (bool){ true } "368": (bool){ true } "369": (bool){ true } "370": (bool){ true } "371": (bool){ true } "372": (bool){ true } "373": (bool){ true } "374": (bool){ true } "375": (bool){ true } "376": (bool){ true } "377": (bool){ true } "378": (bool){ true } "379": (bool){ true } "380": (bool){ true } "381": (bool){ true } "382": (bool){ true } "383": (bool){ true } "384": (bool){ true } "385": (bool){ true } "386": (bool){ true } "387": (bool){ true } "388": (bool){ true } "389": (bool){ true } "390": (bool){ true } "391": (bool){ true } "392": (bool){ true } "393": (bool){ true } "394": (bool){ true } "395": (bool){ true } "396": (bool){ true } "397": (bool){ true } "398": (bool){ true } "399": (bool){ true } "400": (bool){ true } "401": (bool){ true } "402": (bool){ true } "403": (bool){ true } "404": (bool){ true } "405": (bool){ true } "406": (bool){ true } "407": (bool){ true } "408": (bool){ true } "409": (bool){ true } "410": (bool){ true } "411": (bool){ true } "412": (bool){ true } "413": (bool){ true } "414": (bool){ true } "415": (bool){ true } "416": (bool){ true } "417": (bool){ true } "418": (bool){ true } "419": (bool){ true } "420": (bool){ true } "421": (bool){ true } "422": (bool){ true } "423": (bool){ true } "424": (bool){ true } "425": (bool){ true } "426": (bool){ true } "427": (bool){ true } "428": (bool){ true } "429": (bool){ true } "430": (bool){ true } "431": (bool){ true } "432": (bool){ true } "433": (bool){ true } "434": (bool){ true } "435": (bool){ true } "436": (bool){ true } "437": (bool){ true } "438": (bool){ true } "439": (bool){ true } "440": (bool){ true } "441": (bool){ true } "442": (bool){ true } "443": (bool){ true } "444": (bool){ true } "445": (bool){ true } "446": (bool){ true } "447": (bool){ true } "448": (bool){ true } "449": (bool){ true } "450": (bool){ true } "451": (bool){ true } "452": (bool){ true } "453": (bool){ true } "454": (bool){ true } "455": (bool){ true } "456": (bool){ true } "457": (bool){ true } "458": (bool){ true } "459": (bool){ true } "460": (bool){ true } "461": (bool){ true } "462": (bool){ true } "463": (bool){ true } "464": (bool){ true } "465": (bool){ true } "466": (bool){ true } "467": (bool){ true } "468": (bool){ true } "469": (bool){ true } "470": (bool){ true } "471": (bool){ true } "472": (bool){ true } "473": (bool){ true } "474": (bool){ true } "475": (bool){ true } "476": (bool){ true } "477": (bool){ true } "478": (bool){ true } "479": (bool){ true } "480": (bool){ true } "481": (bool){ true } "482": (bool){ true } "483": (bool){ true } "484": (bool){ true } "485": (bool){ true } "486": (bool){ true } "487": (bool){ true } "488": (bool){ true } "489": (bool){ true } "490": (bool){ true } "491": (bool){ true } "492": (bool){ true } "493": (bool){ true } "494": (bool){ true } "495": (bool){ true } "496": (bool){ true } "497": (bool){ true } "498": (bool){ true } "499": (bool){ true } "500": (bool){ true } "501": (bool){ true } "502": (bool){ true } "503": (bool){ true } "504": (bool){ true } "505": (bool){ true } "506": (bool){ true } "507": (bool){ true } "508": (bool){ true } "509": (bool){ true } "510": (bool){ true } "511": (bool){ true } "512": (bool){ true } "513": (bool){ true } "514": (bool){ true } "515": (bool){ true } "516": (bool){ true } "517": (bool){ true } "518": (bool){ true } "519": (bool){ true } "520": (bool){ true } "521": (bool){ true } "522": (bool){ true } "523": (bool){ true } "524": (bool){ true } "525": (bool){ true } "526": (bool){ true } "527": (bool){ true } "528": (bool){ true } "529": (bool){ true } "530": (bool){ true } "531": (bool){ true } "532": (bool){ true } "533": (bool){ true } "534": (bool){ true } "535": (bool){ true } "536": (bool){ true } "537": (bool){ true } "538": (bool){ true } "539": (bool){ true } "540": (bool){ true } "541": (bool){ true } "542": (bool){ true } "543": (bool){ true } "544": (bool){ true } "545": (bool){ true } "546": (bool){ true } "547": (bool){ true } "548": (bool){ true } "549": (bool){ true } "550": (bool){ true } "551": (bool){ true } "552": (bool){ true } "553": (bool){ true } "554": (bool){ true } "555": (bool){ true } "556": (bool){ true } "557": (bool){ true } "558": (bool){ true } "559": (bool){ true } "560": (bool){ true } "561": (bool){ true } "562": (bool){ true } "563": (bool){ true } "564": (bool){ true } "565": (bool){ true } "566": (bool){ true } "567": (bool){ true } "568": (bool){ true } "569": (bool){ true } "570": (bool){ true } "571": (bool){ true } "572": (bool){ true } "573": (bool){ true } "574": (bool){ true } "575": (bool){ true } "576": (bool){ true } "577": (bool){ true } "578": (bool){ true } "579": (bool){ true } "580": (bool){ true } "581": (bool){ true } "582": (bool){ true } "583": (bool){ true } "584": (bool){ true } "585": (bool){ true } "586": (bool){ true } "587": (bool){ true } "588": (bool){ true } "589": (bool){ true } "590": (bool){ true } "591": (bool){ true } "592": (bool){ true } "593": (bool){ true } "594": (bool){ true } "595": (bool){ true } "596": (bool){ true } "597": (bool){ true } "598": (bool){ true } "599": (bool){ true } "600": (bool){ true } "601": (bool){ true } "602": (bool){ true } "603": (bool){ true } "604": (bool){ true } "605": (bool){ true } "606": (bool){ true } "607": (bool){ true } "608": (bool){ true } "609": (bool){ true } "610": (bool){ true } "611": (bool){ true } "612": (bool){ true } "613": (bool){ true } "614": (bool){ true } "615": (bool){ true } "616": (bool){ true } "617": (bool){ true } "618": (bool){ true } "619": (bool){ true } "620": (bool){ true } "621": (bool){ true } "622": (bool){ true } "623": (bool){ true } "624": (bool){ true } "625": (bool){ true } "626": (bool){ true } "627": (bool){ true } "628": (bool){ true } "629": (bool){ true } "630": (bool){ true } "631": (bool){ true } "632": (bool){ true } "633": (bool){ true } "634": (bool){ true } "635": (bool){ true } "636": (bool){ true } "637": (bool){ true } "638": (bool){ true } "639": (bool){ true } "640": (bool){ true } "641": (bool){ true } "642": (bool){ true } "643": (bool){ true } "644": (bool){ true } "645": (bool){ true } "646": (bool){ true } "647": (bool){ true } "648": (bool){ true } "649": (bool){ true } "650": (bool){ true } "651": (bool){ true } "652": (bool){ true } "653": (bool){ true } "654": (bool){ true } "655": (bool){ true } "656": (bool){ true } "657": (bool){ true } "658": (bool){ true } "659": (bool){ true } "660": (bool){ true } "661": (bool){ true } "662": (bool){ true } "663": (bool){ true } "664": (bool){ true } "665": (bool){ true } "666": (bool){ true } "667": (bool){ true } "668": (bool){ true } "669": (bool){ true } "670": (bool){ true } "671": (bool){ true } "672": (bool){ true } "673": (bool){ true } "674": (bool){ true } "675": (bool){ true } "676": (bool){ true } "677": (bool){ true } "678": (bool){ true } "679": (bool){ true } "680": (bool){ true } "681": (bool){ true } "682": (bool){ true } "683": (bool){ true } "684": (bool){ true } "685": (bool){ true } "686": (bool){ true } "687": (bool){ true } "688": (bool){ true } "689": (bool){ true } "690": (bool){ true } "691": (bool){ true } "692": (bool){ true } "693": (bool){ true } "694": (bool){ true } "695": (bool){ true } "696": (bool){ true } "697": (bool){ true } "698": (bool){ true } "699": (bool){ true } "700": (bool){ true } "701": (bool){ true } "702": (bool){ true } "703": (bool){ true } "704": (bool){ true } "705": (bool){ true } "706": (bool){ true } "707": (bool){ true } "708": (bool){ true } "709": (bool){ true } "710": (bool){ true } "711": (bool){ true } "712": (bool){ true } "713": (bool){ true } "714": (bool){ true } "715": (bool){ true } "716": (bool){ true } "717": (bool){ true } "718": (bool){ true } "719": (bool){ true } "720": (bool){ true } "721": (bool){ true } "722": (bool){ true } "723": (bool){ true } "724": (bool){ true } "725": (bool){ true } "726": (bool){ true } "727": (bool){ true } "728": (bool){ true } "729": (bool){ true } "730": (bool){ true } "731": (bool){ true } "732": (bool){ true } "733": (bool){ true } "734": (bool){ true } "735": (bool){ true } "736": (bool){ true } "737": (bool){ true } "738": (bool){ true } "739": (bool){ true } "740": (bool){ true } "741": (bool){ true } "742": (bool){ true } "743": (bool){ true } "744": (bool){ true } "745": (bool){ true } "746": (bool){ true } "747": (bool){ true } "748": (bool){ true } "749": (bool){ true } "750": (bool){ true } "751": (bool){ true } "752": (bool){ true } "753": (bool){ true } "754": (bool){ true } "755": (bool){ true } "756": (bool){ true } "757": (bool){ true } "758": (bool){ true } "759": (bool){ true } "760": (bool){ true } "761": (bool){ true } "762": (bool){ true } "763": (bool){ true } "764": (bool){ true } "765": (bool){ true } "766": (bool){ true } "767": (bool){ true } "768": (bool){ true } "769": (bool){ true } "770": (bool){ true } "771": (bool){ true } "772": (bool){ true } "773": (bool){ true } "774": (bool){ true } "775": (bool){ true } "776": (bool){ true } "777": (bool){ true } "778": (bool){ true } "779": (bool){ true } "780": (bool){ true } "781": (bool){ true } "782": (bool){ true } "783": (bool){ true } "784": (bool){ true } "785": (bool){ true } "786": (bool){ true } "787": (bool){ true } "788": (bool){ true } "789": (bool){ true } "790": (bool){ true } "791": (bool){ true } "792": (bool){ true } "793": (bool){ true } "794": (bool){ true } "795": (bool){ true } "796": (bool){ true } "797": (bool){ true } "798": (bool){ true } "799": (bool){ true } "800": (bool){ true } "801": (bool){ true } "802": (bool){ true } "803": (bool){ true } "804": (bool){ true } "805": (bool){ true } "806": (bool){ true } "807": (bool){ true } "808": (bool){ true } "809": (bool){ true } "810": (bool){ true } "811": (bool){ true } "812": (bool){ true } "813": (bool){ true } "814": (bool){ true } "815": (bool){ true } "816": (bool){ true } "817": (bool){ true } "818": (bool){ true } "819": (bool){ true } "820": (bool){ true } "821": (bool){ true } "822": (bool){ true } "823": (bool){ true } "824": (bool){ true } "825": (bool){ true } "826": (bool){ true } "827": (bool){ true } "828": (bool){ true } "829": (bool){ true } "830": (bool){ true } "831": (bool){ true } "832": (bool){ true } "833": (bool){ true } "834": (bool){ true } "835": (bool){ true } "836": (bool){ true } "837": (bool){ true } "838": (bool){ true } "839": (bool){ true } "840": (bool){ true } "841": (bool){ true } "842": (bool){ true } "843": (bool){ true } "844": (bool){ true } "845": (bool){ true } "846": (bool){ true } "847": (bool){ true } "848": (bool){ true } "849": (bool){ true } "850": (bool){ true } "851": (bool){ true } "852": (bool){ true } "853": (bool){ true } "854": (bool){ true } "855": (bool){ true } "856": (bool){ true } "857": (bool){ true } "858": (bool){ true } "859": (bool){ true } "860": (bool){ true } "861": (bool){ true } "862": (bool){ true } "863": (bool){ true } "864": (bool){ true } "865": (bool){ true } "866": (bool){ true } "867": (bool){ true } "868": (bool){ true } "869": (bool){ true } "870": (bool){ true } "871": (bool){ true } "872": (bool){ true } "873": (bool){ true } "874": (bool){ true } "875": (bool){ true } "876": (bool){ true } "877": (bool){ true } "878": (bool){ true } "879": (bool){ true } "880": (bool){ true } "881": (bool){ true } "882": (bool){ true } "883": (bool){ true } "884": (bool){ true } "885": (bool){ true } "886": (bool){ true } "887": (bool){ true } "888": (bool){ true } "889": (bool){ true } "890": (bool){ true } "891": (bool){ true } "892": (bool){ true } "893": (bool){ true } "894": (bool){ true } "895": (bool){ true } "896": (bool){ true } "897": (bool){ true } "898": (bool){ true } "899": (bool){ true } "900": (bool){ true } "901": (bool){ true } "902": (bool){ true } "903": (bool){ true } "904": (bool){ true } "905": (bool){ true } "906": (bool){ true } "907": (bool){ true } "908": (bool){ true } "909": (bool){ true } "910": (bool){ true } "911": (bool){ true } "912": (bool){ true } "913": (bool){ true } "914": (bool){ true } "915": (bool){ true } "916": (bool){ true } "917": (bool){ true } "918": (bool){ true } "919": (bool){ true } "920": (bool){ true } "921": (bool){ true } "922": (bool){ true } "923": (bool){ true } "924": (bool){ true } "925": (bool){ true } "926": (bool){ true } "927": (bool){ true } "928": (bool){ true } "929": (bool){ true } "930": (bool){ true } "931": (bool){ true } "932": (bool){ true } "933": (bool){ true } "934": (bool){ true } "935": (bool){ true } "936": (bool){ true } "937": (bool){ true } "938": (bool){ true } "939": (bool){ true } "940": (bool){ true } "941": (bool){ true } "942": (bool){ true } "943": (bool){ true } "944": (bool){ true } "945": (bool){ true } "946": (bool){ true } "947": (bool){ true } "948": (bool){ true } "949": (bool){ true } "950": (bool){ true } "951": (bool){ true } "952": (bool){ true } "953": (bool){ true } "954": (bool){ true } "955": (bool){ true } "956": (bool){ true } "957": (bool){ true } "958": (bool){ true } "959": (bool){ true } "960": (bool){ true } "961": (bool){ true } "962": (bool){ true } "963": (bool){ true } "964": (bool){ true } "965": (bool){ true } "966": (bool){ true } "967": (bool){ true } "968": (bool){ true } "969": (bool){ true } "970": (bool){ true } "971": (bool){ true } "972": (bool){ true } "973": (bool){ true } "974": (bool){ true } "975": (bool){ true } "976": (bool){ true } "977": (bool){ true } "978": (bool){ true } "979": (bool){ true } "980": (bool){ true } "981": (bool){ true } "982": (bool){ true } "983": (bool){ true } "984": (bool){ true } "985": (bool){ true } "986": (bool){ true } "987": (bool){ true } "988": (bool){ true } "989": (bool){ true } "990": (bool){ true } "991": (bool){ true } "992": (bool){ true } "993": (bool){ true } "994": (bool){ true } "995": (bool){ true } "996": (bool){ true } "997": (bool){ true } "998": (bool){ true } "999": (bool){ true } "1000": (bool){ true } "1001": (bool){ true } "1002": (bool){ true } "1003": (bool){ true } "1004": (bool){ true } "1005": (bool){ true } "1006": (bool){ true } "1007": (bool){ true } "1008": (bool){ true } "1009": (bool){ true } "1010": (bool){ true } "1011": (bool){ true } "1012": (bool){ true } "1013": (bool){ true } "1014": (bool){ true } "1015": (bool){ true } "1016": (bool){ true } "1017": (bool){ true } "1018": (bool){ true } "1019": (bool){ true } "1020": (bool){ true } "1021": (bool){ true } "1022": (bool){ true } "1023": (bool){ true } "1024": (bool){ true } "1025": (bool){ true } "1026": (bool){ true } "1027": (bool){ true } "1028": (bool){ true } "1029": (bool){ true } "1030": (bool){ true } "1031": (bool){ true } "1032": (bool){ true } "1033": (bool){ true } "1034": (bool){ true } "1035": (bool){ true } "1036": (bool){ true } "1037": (bool){ true } "1038": (bool){ true } "1039": (bool){ true } "1040": (bool){ true } "1041": (bool){ true } "1042": (bool){ true } "1043": (bool){ true } "1044": (bool){ true } "1045": (bool){ true } "1046": (bool){ true } "1047": (bool){ true } "1048": (bool){ true } "1049": (bool){ true } "1050": (bool){ true } "1051": (bool){ true } "1052": (bool){ true } "1053": (bool){ true } "1054": (bool){ true } "1055": (bool){ true } "1056": (bool){ true } "1057": (bool){ true } "1058": (bool){ true } "1059": (bool){ true } "1060": (bool){ true } "1061": (bool){ true } "1062": (bool){ true } "1063": (bool){ true } "1064": (bool){ true } "1065": (bool){ true } "1066": (bool){ true } "1067": (bool){ true } "1068": (bool){ true } "1069": (bool){ true } "1070": (bool){ true } "1071": (bool){ true } "1072": (bool){ true } "1073": (bool){ true } "1074": (bool){ true } "1075": (bool){ true } "1076": (bool){ true } "1077": (bool){ true } "1078": (bool){ true } "1079": (bool){ true } "1080": (bool){ true } "1081": (bool){ true } "1082": (bool){ true } "1083": (bool){ true } "1084": (bool){ true } "1085": (bool){ true } "1086": (bool){ true } "1087": (bool){ true } "1088": (bool){ true } "1089": (bool){ true } "1090": (bool){ true } "1091": (bool){ true } "1092": (bool){ true } "1093": (bool){ true } "1094": (bool){ true } "1095": (bool){ true } "1096": (bool){ true } "1097": (bool){ true } "1098": (bool){ true } "1099": (bool){ true } "1100": (bool){ true } "1101": (bool){ true } "1102": (bool){ true } "1103": (bool){ true } "1104": (bool){ true } "1105": (bool){ true } "1106": (bool){ true } "1107": (bool){ true } "1108": (bool){ true } "1109": (bool){ true } "1110": (bool){ true } "1111": (bool){ true } "1112": (bool){ true } "1113": (bool){ true } "1114": (bool){ true } "1115": (bool){ true } "1116": (bool){ true } "1117": (bool){ true } "1118": (bool){ true } "1119": (bool){ true } "1120": (bool){ true } "1121": (bool){ true } "1122": (bool){ true } "1123": (bool){ true } "1124": (bool){ true } "1125": (bool){ true } "1126": (bool){ true } "1127": (bool){ true } "1128": (bool){ true } "1129": (bool){ true } "1130": (bool){ true } "1131": (bool){ true } "1132": (bool){ true } "1133": (bool){ true } "1134": (bool){ true } "1135": (bool){ true } "1136": (bool){ true } "1137": (bool){ true } "1138": (bool){ true } "1139": (bool){ true } "1140": (bool){ true } "1141": (bool){ true } "1142": (bool){ true } "1143": (bool){ true } "1144": (bool){ true } "1145": (bool){ true } "1146": (bool){ true } "1147": (bool){ true } "1148": (bool){ true } "1149": (bool){ true } "1150": (bool){ true } "1151": (bool){ true } "1152": (bool){ true } "1153": (bool){ true } "1154": (bool){ true } "1155": (bool){ true } "1156": (bool){ true } "1157": (bool){ true } "1158": (bool){ true } "1159": (bool){ true } "1160": (bool){ true } "1161": (bool){ true } "1162": (bool){ true } "1163": (bool){ true } "1164": (bool){ true } "1165": (bool){ true } "1166": (bool){ true } "1167": (bool){ true } "1168": (bool){ true } "1169": (bool){ true } "1170": (bool){ true } "1171": (bool){ true } "1172": (bool){ true } "1173": (bool){ true } "1174": (bool){ true } "1175": (bool){ true } "1176": (bool){ true } "1177": (bool){ true } "1178": (bool){ true } "1179": (bool){ true } "1180": (bool){ true } "1181": (bool){ true } "1182": (bool){ true } "1183": (bool){ true } "1184": (bool){ true } "1185": (bool){ true } "1186": (bool){ true } "1187": (bool){ true } "1188": (bool){ true } "1189": (bool){ true } "1190": (bool){ true } "1191": (bool){ true } "1192": (bool){ true } "1193": (bool){ true } "1194": (bool){ true } "1195": (bool){ true } "1196": (bool){ true } "1197": (bool){ true } "1198": (bool){ true } "1199": (bool){ true } "1200": (bool){ true } "1201": (bool){ true } "1202": (bool){ true } "1203": (bool){ true } "1204": (bool){ true } "1205": (bool){ true } "1206": (bool){ true } "1207": (bool){ true } "1208": (bool){ true } "1209": (bool){ true } "1210": (bool){ true } "1211": (bool){ true } "1212": (bool){ true } "1213": (bool){ true } "1214": (bool){ true } "1215": (bool){ true } "1216": (bool){ true } "1217": (bool){ true } "1218": (bool){ true } "1219": (bool){ true } "1220": (bool){ true } "1221": (bool){ true } "1222": (bool){ true } "1223": (bool){ true } "1224": (bool){ true } "1225": (bool){ true } "1226": (bool){ true } "1227": (bool){ true } "1228": (bool){ true } "1229": (bool){ true } "1230": (bool){ true } "1231": (bool){ true } "1232": (bool){ true } "1233": (bool){ true } "1234": (bool){ true } "1235": (bool){ true } "1236": (bool){ true } "1237": (bool){ true } "1238": (bool){ true } "1239": (bool){ true } "1240": (bool){ true } "1241": (bool){ true } "1242": (bool){ true } "1243": (bool){ true } "1244": (bool){ true } "1245": (bool){ true } "1246": (bool){ true } "1247": (bool){ true } "1248": (bool){ true } "1249": (bool){ true } "1250": (bool){ true } "1251": (bool){ true } "1252": (bool){ true } "1253": (bool){ true } "1254": (bool){ true } "1255": (bool){ true } "1256": (bool){ true } "1257": (bool){ true } "1258": (bool){ true } "1259": (bool){ true } "1260": (bool){ true } "1261": (bool){ true } "1262": (bool){ true } "1263": (bool){ true } "1264": (bool){ true } "1265": (bool){ true } "1266": (bool){ true } "1267": (bool){ true } "1268": (bool){ true } "1269": (bool){ true } "1270": (bool){ true } "1271": (bool){ true } "1272": (bool){ true } "1273": (bool){ true } "1274": (bool){ true } "1275": (bool){ true } "1276": (bool){ true } "1277": (bool){ true } "1278": (bool){ true } "1279": (bool){ true } "1280": (bool){ true } "1281": (bool){ true } "1282": (bool){ true } "1283": (bool){ true } "1284": (bool){ true } "1285": (bool){ true } "1286": (bool){ true } "1287": (bool){ true } "1288": (bool){ true } "1289": (bool){ true } "1290": (bool){ true } "1291": (bool){ true } "1292": (bool){ true } "1293": (bool){ true } "1294": (bool){ true } "1295": (bool){ true } "1296": (bool){ true } "1297": (bool){ true } "1298": (bool){ true } "1299": (bool){ true } "1300": (bool){ true } "1301": (bool){ true } "1302": (bool){ true } "1303": (bool){ true } "1304": (bool){ true } "1305": (bool){ true } "1306": (bool){ true } "1307": (bool){ true } "1308": (bool){ true } "1309": (bool){ true } "1310": (bool){ true } "1311": (bool){ true } "1312": (bool){ true } "1313": (bool){ true } "1314": (bool){ true } "1315": (bool){ true } "1316": (bool){ true } "1317": (bool){ true } "1318": (bool){ true } "1319": (bool){ true } "1320": (bool){ true } "1321": (bool){ true } "1322": (bool){ true } "1323": (bool){ true } "1324": (bool){ true } "1325": (bool){ true } "1326": (bool){ true } "1327": (bool){ true } "1328": (bool){ true } "1329": (bool){ true } "1330": (bool){ true } "1331": (bool){ true } "1332": (bool){ true } "1333": (bool){ true } "1334": (bool){ true } "1335": (bool){ true } "1336": (bool){ true } "1337": (bool){ true } "1338": (bool){ true } "1339": (bool){ true } "1340": (bool){ true } "1341": (bool){ true } "1342": (bool){ true } "1343": (bool){ true } "1344": (bool){ true } "1345": (bool){ true } "1346": (bool){ true } "1347": (bool){ true } "1348": (bool){ true } "1349": (bool){ true } "1350": (bool){ true } "1351": (bool){ true } "1352": (bool){ true } "1353": (bool){ true } "1354": (bool){ true } "1355": (bool){ true } "1356": (bool){ true } "1357": (bool){ true } "1358": (bool){ true } "1359": (bool){ true } "1360": (bool){ true } "1361": (bool){ true } "1362": (bool){ true } "1363": (bool){ true } "1364": (bool){ true } "1365": (bool){ true } "1366": (bool){ true } "1367": (bool){ true } "1368": (bool){ true } "1369": (bool){ true } "1370": (bool){ true } "1371": (bool){ true } "1372": (bool){ true } "1373": (bool){ true } "1374": (bool){ true } "1375": (bool){ true } "1376": (bool){ true } "1377": (bool){ true } "1378": (bool){ true } "1379": (bool){ true } "1380": (bool){ true } "1381": (bool){ true } "1382": (bool){ true } "1383": (bool){ true } "1384": (bool){ true } "1385": (bool){ true } "1386": (bool){ true } "1387": (bool){ true } "1388": (bool){ true } "1389": (bool){ true } "1390": (bool){ true } "1391": (bool){ true } "1392": (bool){ true } "1393": (bool){ true } "1394": (bool){ true } "1395": (bool){ true } "1396": (bool){ true } "1397": (bool){ true } "1398": (bool){ true } "1399": (bool){ true } "1400": (bool){ true } "1401": (bool){ true } "1402": (bool){ true } "1403": (bool){ true } "1404": (bool){ true } "1405": (bool){ true } "1406": (bool){ true } "1407": (bool){ true } "1408": (bool){ true } "1409": (bool){ true } "1410": (bool){ true } "1411": (bool){ true } "1412": (bool){ true } "1413": (bool){ true } "1414": (bool){ true } "1415": (bool){ true } "1416": (bool){ true } "1417": (bool){ true } "1418": (bool){ true } "1419": (bool){ true } "1420": (bool){ true } "1421": (bool){ true } "1422": (bool){ true } "1423": (bool){ true } "1424": (bool){ true } "1425": (bool){ true } "1426": (bool){ true } "1427": (bool){ true } "1428": (bool){ true } "1429": (bool){ true } "1430": (bool){ true } "1431": (bool){ true } "1432": (bool){ true } "1433": (bool){ true } "1434": (bool){ true } "1435": (bool){ true } "1436": (bool){ true } "1437": (bool){ true } "1438": (bool){ true } "1439": (bool){ true } "1440": (bool){ true } "1441": (bool){ true } "1442": (bool){ true } "1443": (bool){ true } "1444": (bool){ true } "1445": (bool){ true } "1446": (bool){ true } "1447": (bool){ true } "1448": (bool){ true } "1449": (bool){ true } "1450": (bool){ true } "1451": (bool){ true } "1452": (bool){ true } "1453": (bool){ true } "1454": (bool){ true } "1455": (bool){ true } "1456": (bool){ true } "1457": (bool){ true } "1458": (bool){ true } "1459": (bool){ true } "1460": (bool){ true } "1461": (bool){ true } "1462": (bool){ true } "1463": (bool){ true } "1464": (bool){ true } "1465": (bool){ true } "1466": (bool){ true } "1467": (bool){ true } "1468": (bool){ true } "1469": (bool){ true } "1470": (bool){ true } "1471": (bool){ true } "1472": (bool){ true } "1473": (bool){ true } "1474": (bool){ true } "1475": (bool){ true } "1476": (bool){ true } "1477": (bool){ true } "1478": (bool){ true } "1479": (bool){ true } "1480": (bool){ true } "1481": (bool){ true } "1482": (bool){ true } "1483": (bool){ true } "1484": (bool){ true } "1485": (bool){ true } "1486": (bool){ true } "1487": (bool){ true } "1488": (bool){ true } "1489": (bool){ true } "1490": (bool){ true } "1491": (bool){ true } "1492": (bool){ true } "1493": (bool){ true } "1494": (bool){ true } "1495": (bool){ true } "1496": (bool){ true } "1497": (bool){ true } "1498": (bool){ true } "1499": (bool){ true } } } -- out/compile -- --- in.cue { _entries: [ for _, i in 〈import;list〉.Range(1, 1500, 1) { 〈1;i〉 }, ] unified: { for _, entry in 〈1;_entries〉 { "\(〈1;entry〉)": true } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/listdedup.txtar000066400000000000000000000333331474664451600242700ustar00rootroot00000000000000#Issue: 758 #Issue: 1044 // TODO(perf): reduce number of conjunctions and disjunctions. -- stats.txt -- Leaks: 0 Freed: 24096 Reused: 24051 Allocs: 45 Retain: 1 Unifications: 18724 Conjuncts: 100730 Disjuncts: 24097 -- in.cue -- A: #Task B: #steps: #Script & {mount: [A]} C: #steps: #Script & {mount: [B]} #Script: {mount: [...#Task]} #Task: { // Without the proper constructs, repeating the below results // in exponential runtime. #ref #ref _ | {} _ | {} #steps: #Script ... } #ref: {a: 1} | {b: 2} -- out/evalalpha/stats -- Leaks: 168 Freed: 0 Reused: 0 Allocs: 168 Retain: 0 Unifications: 56 Conjuncts: 480 Disjuncts: 40 -- out/evalalpha -- (struct){ A: (#struct){ |((#struct){ #steps: ~(#Script) a: (int){ 1 } }, (#struct){ #steps: ~(#Script) a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: ~(#Script) b: (int){ 2 } }) } B: (struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: ~(#Script) a: (int){ 1 } }, (#struct){ #steps: ~(#Script) a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: ~(#Script) b: (int){ 2 } }) } } } } C: (struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: ~(#Script) a: (int){ 1 } }, (#struct){ #steps: ~(#Script) a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: ~(#Script) b: (int){ 2 } }) } } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: ~(#Script) a: (int){ 1 } }, (#struct){ #steps: ~(#Script) a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: ~(#Script) b: (int){ 2 } }) } } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: ~(#Script) a: (int){ 1 } }, (#struct){ #steps: ~(#Script) a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: ~(#Script) b: (int){ 2 } }) } } } b: (int){ 2 } }) } } } } #Script: (#struct){ mount: (list){ } } #Task: (#struct){ |((#struct){ #steps: ~(#Script) a: (int){ 1 } }, (#struct){ #steps: ~(#Script) a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: ~(#Script) b: (int){ 2 } }) } #ref: (#struct){ |((#struct){ a: (int){ 1 } }, (#struct){ b: (int){ 2 } }) } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,22 +1,13 @@ (struct){ A: (#struct){ |((#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: ~(#Script) b: (int){ 2 } }) } B: (struct){ @@ -23,23 +14,14 @@ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: ~(#Script) b: (int){ 2 } }) } } @@ -52,76 +34,49 @@ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - b: (int){ 2 } - }) } - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (#list){ - 0: (#struct){ |((#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - b: (int){ 2 } - }) } - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (#list){ - 0: (#struct){ |((#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + } + } + a: (int){ 1 } + }, (#struct){ + #steps: (#struct){ + mount: (#list){ + 0: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: ~(#Script) + b: (int){ 2 } + }) } + } + } + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: (#struct){ + mount: (#list){ + 0: (#struct){ |((#struct){ + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: ~(#Script) b: (int){ 2 } }) } } @@ -136,23 +91,14 @@ } } #Task: (#struct){ |((#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - #steps: (#struct){ - mount: (list){ - } - } + #steps: ~(#Script) + a: (int){ 1 } + }, (#struct){ + #steps: ~(#Script) + a: (int){ 1 } + b: (int){ 2 } + }, (#struct){ + #steps: ~(#Script) b: (int){ 2 } }) } #ref: (#struct){ |((#struct){ -- out/eval -- (struct){ A: (#struct){ |((#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (list){ } } b: (int){ 2 } }) } B: (struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (list){ } } b: (int){ 2 } }) } } } } C: (struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (list){ } } b: (int){ 2 } }) } } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (list){ } } b: (int){ 2 } }) } } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (#list){ 0: (#struct){ |((#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (list){ } } b: (int){ 2 } }) } } } b: (int){ 2 } }) } } } } #Script: (#struct){ mount: (list){ } } #Task: (#struct){ |((#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } }, (#struct){ #steps: (#struct){ mount: (list){ } } a: (int){ 1 } b: (int){ 2 } }, (#struct){ #steps: (#struct){ mount: (list){ } } b: (int){ 2 } }) } #ref: (#struct){ |((#struct){ a: (int){ 1 } }, (#struct){ b: (int){ 2 } }) } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 24096 -Reused: 24051 -Allocs: 45 -Retain: 1 +Leaks: 168 +Freed: 0 +Reused: 0 +Allocs: 168 +Retain: 0 -Unifications: 18724 -Conjuncts: 100730 -Disjuncts: 24097 +Unifications: 56 +Conjuncts: 480 +Disjuncts: 40 -- out/eval/stats -- Leaks: 0 Freed: 24096 Reused: 24051 Allocs: 45 Retain: 1 Unifications: 18724 Conjuncts: 100730 Disjuncts: 24097 -- out/compile -- --- in.cue { A: 〈0;#Task〉 B: { #steps: (〈1;#Script〉 & { mount: [ 〈3;A〉, ] }) } C: { #steps: (〈1;#Script〉 & { mount: [ 〈3;B〉, ] }) } #Script: { mount: [ ...〈2;#Task〉, ] } #Task: { 〈1;#ref〉 〈1;#ref〉 (_|{}) (_|{}) #steps: 〈1;#Script〉 ... } #ref: ({ a: 1 }|{ b: 2 }) } cue-lang-cue-db9cc73/cue/testdata/benchmarks/listdisj.txtar000066400000000000000000000037631474664451600241240ustar00rootroot00000000000000#Issue: 1940 -- stats.txt -- Leaks: 0 Freed: 447 Reused: 439 Allocs: 8 Retain: 0 Unifications: 287 Conjuncts: 894 Disjuncts: 447 -- in.cue -- #T: ["a", #T] | ["b", #T] | ["c", #T] | ["d", ...#T] x: #T y: #T z: #T v: #T #X: x #X: y #X: z #X: v #X: #T -- out/compile -- --- in.cue { #T: ([ "a", 〈1;#T〉, ]|[ "b", 〈1;#T〉, ]|[ "c", 〈1;#T〉, ]|[ "d", ...〈1;#T〉, ]) x: 〈0;#T〉 y: 〈0;#T〉 z: 〈0;#T〉 v: 〈0;#T〉 #X: 〈0;x〉 #X: 〈0;y〉 #X: 〈0;z〉 #X: 〈0;v〉 #X: 〈0;#T〉 } -- out/evalalpha/stats -- Leaks: 16 Freed: 3 Reused: 3 Allocs: 16 Retain: 0 Unifications: 15 Conjuncts: 44 Disjuncts: 4 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 447 -Reused: 439 -Allocs: 8 +Leaks: 16 +Freed: 3 +Reused: 3 +Allocs: 16 Retain: 0 -Unifications: 287 -Conjuncts: 894 -Disjuncts: 447 +Unifications: 15 +Conjuncts: 44 +Disjuncts: 4 -- out/evalalpha -- (struct){ #T: (list){ 0: (string){ "d" } } x: ~(#T) y: ~(#T) z: ~(#T) v: ~(#T) #X: ~(#T) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,19 +2,9 @@ #T: (list){ 0: (string){ "d" } } - x: (list){ - 0: (string){ "d" } - } - y: (list){ - 0: (string){ "d" } - } - z: (list){ - 0: (string){ "d" } - } - v: (list){ - 0: (string){ "d" } - } - #X: (list){ - 0: (string){ "d" } - } + x: ~(#T) + y: ~(#T) + z: ~(#T) + v: ~(#T) + #X: ~(#T) } -- out/eval -- (struct){ #T: (list){ 0: (string){ "d" } } x: (list){ 0: (string){ "d" } } y: (list){ 0: (string){ "d" } } z: (list){ 0: (string){ "d" } } v: (list){ 0: (string){ "d" } } #X: (list){ 0: (string){ "d" } } } -- diff/explanation -- Differences fully due to rendered structure sharing. -- out/eval/stats -- Leaks: 0 Freed: 447 Reused: 439 Allocs: 8 Retain: 0 Unifications: 287 Conjuncts: 894 Disjuncts: 447 cue-lang-cue-db9cc73/cue/testdata/benchmarks/mergeddisjunction.txtar000066400000000000000000000124211474664451600260030ustar00rootroot00000000000000// Here one comprehension creates a number of distinct values, each of which // with a disjunction, then another comprehension maps them back to the // same value, creating a large number of disjunctions. // // The disjunctions cannot be identified as equal in the general case. If no // care is taken, disjunction elimination will be exponential, causing over // a billion disjuncts to process in the below example. With the proper // optimizations, there is a small, constant number of disjunction ops per // disjunct. // // Issue #651 -- stats.txt -- Leaks: 0 Freed: 283 Reused: 275 Allocs: 8 Retain: 0 Unifications: 99 Conjuncts: 530 Disjuncts: 283 -- in.cue -- list: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, ] a: [X=string]: text: *"default" | string a: { for i in list { "\(i)": text: string } } b: { for x in a { "\(x.text)": {text: x.text} } } -- out/eval/stats -- Leaks: 0 Freed: 283 Reused: 275 Allocs: 8 Retain: 0 Unifications: 99 Conjuncts: 530 Disjuncts: 283 -- out/eval -- (struct){ list: (#list){ 0: (int){ 0 } 1: (int){ 1 } 2: (int){ 2 } 3: (int){ 3 } 4: (int){ 4 } 5: (int){ 5 } 6: (int){ 6 } 7: (int){ 7 } 8: (int){ 8 } 9: (int){ 9 } 10: (int){ 10 } 11: (int){ 11 } 12: (int){ 12 } 13: (int){ 13 } 14: (int){ 14 } 15: (int){ 15 } 16: (int){ 16 } 17: (int){ 17 } 18: (int){ 18 } 19: (int){ 19 } 20: (int){ 20 } 21: (int){ 21 } 22: (int){ 22 } 23: (int){ 23 } 24: (int){ 24 } 25: (int){ 25 } 26: (int){ 26 } 27: (int){ 27 } 28: (int){ 28 } 29: (int){ 29 } 30: (int){ 30 } } a: (struct){ "0": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "1": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "2": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "3": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "4": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "5": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "6": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "7": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "8": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "9": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "10": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "11": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "12": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "13": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "14": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "15": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "16": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "17": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "18": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "19": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "20": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "21": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "22": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "23": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "24": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "25": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "26": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "27": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "28": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "29": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } "30": (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } } b: (struct){ default: (struct){ text: (string){ |(*(string){ "default" }, (string){ string }) } } } } -- out/compile -- --- in.cue { list: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, ] a: { [string]: { text: (*"default"|string) } } a: { for _, i in 〈1;list〉 { "\(〈1;i〉)": { text: string } } } b: { for _, x in 〈1;a〉 { "\(〈1;x〉.text)": { text: 〈2;x〉.text } } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/share.txtar000066400000000000000000005023571474664451600234040ustar00rootroot00000000000000See https://en.wikipedia.org/wiki/Billion_laughs_attack. -- in.cue -- f: [g, g, g, g, g, g, g] g: [h, h, h, h, h, h, h] h: [i, i, i, i, i, i, i] i: [j, j, j, j, j, j, j] j: 1 -- out/compile -- --- in.cue { f: [ 〈1;g〉, 〈1;g〉, 〈1;g〉, 〈1;g〉, 〈1;g〉, 〈1;g〉, 〈1;g〉, ] g: [ 〈1;h〉, 〈1;h〉, 〈1;h〉, 〈1;h〉, 〈1;h〉, 〈1;h〉, 〈1;h〉, ] h: [ 〈1;i〉, 〈1;i〉, 〈1;i〉, 〈1;i〉, 〈1;i〉, 〈1;i〉, 〈1;i〉, ] i: [ 〈1;j〉, 〈1;j〉, 〈1;j〉, 〈1;j〉, 〈1;j〉, 〈1;j〉, 〈1;j〉, ] j: 1 } -- out/evalalpha/stats -- Leaks: 34 Freed: 0 Reused: 0 Allocs: 34 Retain: 0 Unifications: 34 Conjuncts: 95 Disjuncts: 0 -- out/evalalpha -- (struct){ f: (#list){ 0: ~(g) 1: ~(g) 2: ~(g) 3: ~(g) 4: ~(g) 5: ~(g) 6: ~(g) } g: (#list){ 0: ~(h) 1: ~(h) 2: ~(h) 3: ~(h) 4: ~(h) 5: ~(h) 6: ~(h) } h: (#list){ 0: ~(i) 1: ~(i) 2: ~(i) 3: ~(i) 4: ~(i) 5: ~(i) 6: ~(i) } i: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } j: (int){ 1 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,3726 +1,30 @@ (struct){ f: (#list){ - 0: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } - 1: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } - 2: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } - 3: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } - 4: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } - 5: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } - 6: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - } + 0: ~(g) + 1: ~(g) + 2: ~(g) + 3: ~(g) + 4: ~(g) + 5: ~(g) + 6: ~(g) } g: (#list){ - 0: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 1: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 2: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 3: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 4: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 5: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } - 6: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - } + 0: ~(h) + 1: ~(h) + 2: ~(h) + 3: ~(h) + 4: ~(h) + 5: ~(h) + 6: ~(h) } h: (#list){ - 0: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 1: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 2: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 3: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 4: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 5: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } - 6: (#list){ - 0: (int){ 1 } - 1: (int){ 1 } - 2: (int){ 1 } - 3: (int){ 1 } - 4: (int){ 1 } - 5: (int){ 1 } - 6: (int){ 1 } - } + 0: ~(i) + 1: ~(i) + 2: ~(i) + 3: ~(i) + 4: ~(i) + 5: ~(i) + 6: ~(i) } i: (#list){ 0: (int){ 1 } -- out/eval -- (struct){ f: (#list){ 0: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } 1: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } 2: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } 3: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } 4: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } 5: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } 6: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } } g: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 1: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 2: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 3: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 4: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 5: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } 6: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } } h: (#list){ 0: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 1: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 2: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 3: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 4: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 5: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } 6: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } } i: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } 4: (int){ 1 } 5: (int){ 1 } 6: (int){ 1 } } j: (int){ 1 } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 3268 -Reused: 3258 -Allocs: 10 -Retain: 2803 +Leaks: 34 +Freed: 0 +Reused: 0 +Allocs: 34 +Retain: 0 -Unifications: 3268 -Conjuncts: 6529 -Disjuncts: 3271 +Unifications: 34 +Conjuncts: 95 +Disjuncts: 0 -- out/eval/stats -- Leaks: 0 Freed: 3268 Reused: 3258 Allocs: 10 Retain: 2803 Unifications: 3268 Conjuncts: 6529 Disjuncts: 3271 cue-lang-cue-db9cc73/cue/testdata/benchmarks/sharefg.txtar000066400000000000000000001166631474664451600237220ustar00rootroot00000000000000# This file has fine-grained sharing tests. -- in.cue -- // In each case, the number of output nodes should be linear in the input size. // // This means that in each case, the next line should not retrigger the // computation of the previous field. // 26 Nodes computed: // f1: 5 // f2+: +3 each binexpr: { f1: { out: x: 2 } f2: { out: x: f1.out.x + 1 } f3: { out: x: f2.out.x + 1 } f4: { out: x: f3.out.x + 1 } f5: { out: x: f4.out.x + 1 } f6: { out: x: f5.out.x + 1 } f7: { out: x: f6.out.x + 1 } f8: { out: x: f7.out.x + 1 } } // 26 Nodes computed: // f1: 5 // f2+: +3 each parenthesized: { f1: { out: x: 2 } f2: { out: x: (f1.out).x + 1 } f3: { out: x: (f2.out).x + 1 } f4: { out: x: (f3.out).x + 1 } f5: { out: x: (f4.out).x + 1 } f6: { out: x: (f5.out).x + 1 } f7: { out: x: (f6.out).x + 1 } f8: { out: x: (f7.out).x + 1 } } // TODO(perf): fix // 82 Nodes computed [O(n^2)]: // f1: 5 // fn: +(n*2 + 1) // SHOULD BE: // 26 Nodes computed: // f1: 5 // f2+: +3 each embedded: { f1: { out: x: 2 } f2: { out: x: {f1.out}.x + 1 } f3: { out: x: {f2.out}.x + 1 } f4: { out: x: {f3.out}.x + 1 } f5: { out: x: {f4.out}.x + 1 } f6: { out: x: {f5.out}.x + 1 } f7: { out: x: {f6.out}.x + 1 } f8: { out: x: {f7.out}.x + 1 } } // TODO(perf): fix // 82 Nodes computed [O(n^2)]: // f1: 5 // fn: +(n*2 + 1) each // SHOULD BE: // 26 Nodes computed: // f1: 5 // f2+: +3 each embeddedWithEmpty: { f1: { out: x: 2 } f2: { out: x: {f1.out & {}}.x + 1 } f3: { out: x: {f2.out & {}}.x + 1 } f4: { out: x: {f3.out & {}}.x + 1 } f5: { out: x: {f4.out & {}}.x + 1 } f6: { out: x: {f5.out & {}}.x + 1 } f7: { out: x: {f6.out & {}}.x + 1 } f8: { out: x: {f7.out & {}}.x + 1 } } // TODO(perf): fix // This will visualize O(n^2) output size unless CUE allows for a bit more // sophisticated sharing. weave: { f: X={ out: in + 1 in: X.ref.out + 1 ref: _ & {} } f8: f&{ ref: f7 } f7: f&{ ref: f6 } f6: f&{ ref: f5 } f5: f&{ ref: f4 } f4: f&{ ref: f3 } f3: f&{ ref: f2 } f2: f&{ ref: f1 } f1: { out: 2 } } // TODO(perf): fix // This will visualize O(n^2) output size unless CUE supports fine-grained // sharing. weaveExtraField: { f: X={ out: in + 1 in: X.ref.out + 1 ref: {y: 4} // Cannot share because of this, but sub arcs still can be. } f8: f&{ ref: f7 } f7: f&{ ref: f6 } f6: f&{ ref: f5 } f5: f&{ ref: f4 } f4: f&{ ref: f3 } f3: f&{ ref: f2 } f2: f&{ ref: f1 } f1: { out: 2 } } -- out/eval/stats -- Leaks: 112 Freed: 340 Reused: 308 Allocs: 144 Retain: 428 Unifications: 452 Conjuncts: 853 Disjuncts: 720 -- out/evalalpha -- (struct){ binexpr: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } parenthesized: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } embedded: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } embeddedWithEmpty: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } weave: (struct){ f: (struct){ out: (_|_){ // [incomplete] weave.f.in: undefined field: out: // ./in.cue:78:14 } in: (_|_){ // [incomplete] weave.f.in: undefined field: out: // ./in.cue:78:14 } ref: (struct){ } } f8: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } out: (int){ 12 } in: (int){ 11 } } out: (int){ 14 } in: (int){ 13 } } out: (int){ 16 } in: (int){ 15 } } f7: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } out: (int){ 12 } in: (int){ 11 } } out: (int){ 14 } in: (int){ 13 } } f6: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } out: (int){ 12 } in: (int){ 11 } } f5: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } f4: (struct){ ref: (struct){ ref: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } f3: (struct){ ref: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } f2: (struct){ ref: (struct){ out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } f1: (struct){ out: (int){ 2 } } } weaveExtraField: (struct){ f: (struct){ out: (_|_){ // [incomplete] weaveExtraField.f.in: undefined field: out: // ./in.cue:97:14 } in: (_|_){ // [incomplete] weaveExtraField.f.in: undefined field: out: // ./in.cue:97:14 } ref: (struct){ y: (int){ 4 } } } f8: (struct){ ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } out: (int){ 12 } in: (int){ 11 } } out: (int){ 14 } in: (int){ 13 } } out: (int){ 16 } in: (int){ 15 } } f7: (struct){ ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } out: (int){ 12 } in: (int){ 11 } } out: (int){ 14 } in: (int){ 13 } } f6: (struct){ ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } out: (int){ 12 } in: (int){ 11 } } f5: (struct){ ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } out: (int){ 10 } in: (int){ 9 } } f4: (struct){ ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } out: (int){ 8 } in: (int){ 7 } } f3: (struct){ ref: (struct){ y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } out: (int){ 6 } in: (int){ 5 } } f2: (struct){ ref: (struct){ y: (int){ 4 } out: (int){ 2 } } out: (int){ 4 } in: (int){ 3 } } f1: (struct){ out: (int){ 2 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -170,148 +170,148 @@ weave: (struct){ f: (struct){ out: (_|_){ - // [cycle] cycle error: - // ./in.cue:77:8 - } - in: (_|_){ - // [incomplete] weave.f.in: undefined field: out: - // ./in.cue:78:14 - } - ref: (struct){ - } - } - f8: (struct){ - out: (int){ 16 } - in: (int){ 15 } - ref: (struct){ - out: (int){ 14 } - in: (int){ 13 } - ref: (struct){ - out: (int){ 12 } - in: (int){ 11 } - ref: (struct){ - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } - } - } - } - } - } - } - } - f7: (struct){ - out: (int){ 14 } - in: (int){ 13 } - ref: (struct){ - out: (int){ 12 } - in: (int){ 11 } - ref: (struct){ - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } - } - } - } - } - } - } - f6: (struct){ - out: (int){ 12 } - in: (int){ 11 } - ref: (struct){ - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } - } - } - } - } - } - f5: (struct){ - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } - } - } - } - } - f4: (struct){ - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } - } - } - } - f3: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } - } - } - f2: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - out: (int){ 2 } - } + // [incomplete] weave.f.in: undefined field: out: + // ./in.cue:78:14 + } + in: (_|_){ + // [incomplete] weave.f.in: undefined field: out: + // ./in.cue:78:14 + } + ref: (struct){ + } + } + f8: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + out: (int){ 12 } + in: (int){ 11 } + } + out: (int){ 14 } + in: (int){ 13 } + } + out: (int){ 16 } + in: (int){ 15 } + } + f7: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + out: (int){ 12 } + in: (int){ 11 } + } + out: (int){ 14 } + in: (int){ 13 } + } + f6: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + out: (int){ 12 } + in: (int){ 11 } + } + f5: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + f4: (struct){ + ref: (struct){ + ref: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + f3: (struct){ + ref: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + f2: (struct){ + ref: (struct){ + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } } f1: (struct){ out: (int){ 2 } @@ -320,177 +320,177 @@ weaveExtraField: (struct){ f: (struct){ out: (_|_){ - // [cycle] cycle error: - // ./in.cue:96:8 - } - in: (_|_){ - // [incomplete] weaveExtraField.f.in: undefined field: out: - // ./in.cue:97:14 - } - ref: (struct){ - y: (int){ 4 } - } - } - f8: (struct){ - out: (int){ 16 } - in: (int){ 15 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 14 } - in: (int){ 13 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 12 } - in: (int){ 11 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 4 } - in: (int){ 3 } + // [incomplete] weaveExtraField.f.in: undefined field: out: + // ./in.cue:97:14 + } + in: (_|_){ + // [incomplete] weaveExtraField.f.in: undefined field: out: + // ./in.cue:97:14 + } + ref: (struct){ + y: (int){ 4 } + } + } + f8: (struct){ + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } - } - } - } - } - } - } - } - f7: (struct){ - out: (int){ 14 } - in: (int){ 13 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 12 } - in: (int){ 11 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 2 } - } - } - } - } - } - } - } - f6: (struct){ - out: (int){ 12 } - in: (int){ 11 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 2 } - } - } - } - } - } - } - f5: (struct){ - out: (int){ 10 } - in: (int){ 9 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 2 } - } - } - } - } - } - f4: (struct){ - out: (int){ 8 } - in: (int){ 7 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 2 } - } - } - } - } - f3: (struct){ - out: (int){ 6 } - in: (int){ 5 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 2 } - } - } - } - f2: (struct){ - out: (int){ 4 } - in: (int){ 3 } - ref: (struct){ - y: (int){ 4 } - out: (int){ 2 } - } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + out: (int){ 12 } + in: (int){ 11 } + } + out: (int){ 14 } + in: (int){ 13 } + } + out: (int){ 16 } + in: (int){ 15 } + } + f7: (struct){ + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + out: (int){ 12 } + in: (int){ 11 } + } + out: (int){ 14 } + in: (int){ 13 } + } + f6: (struct){ + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + out: (int){ 12 } + in: (int){ 11 } + } + f5: (struct){ + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + out: (int){ 10 } + in: (int){ 9 } + } + f4: (struct){ + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + out: (int){ 8 } + in: (int){ 7 } + } + f3: (struct){ + ref: (struct){ + y: (int){ 4 } + ref: (struct){ + y: (int){ 4 } + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } + } + out: (int){ 6 } + in: (int){ 5 } + } + f2: (struct){ + ref: (struct){ + y: (int){ 4 } + out: (int){ 2 } + } + out: (int){ 4 } + in: (int){ 3 } } f1: (struct){ out: (int){ 2 } -- out/eval -- (struct){ binexpr: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } parenthesized: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } embedded: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } embeddedWithEmpty: (struct){ f1: (struct){ out: (struct){ x: (int){ 2 } } } f2: (struct){ out: (struct){ x: (int){ 3 } } } f3: (struct){ out: (struct){ x: (int){ 4 } } } f4: (struct){ out: (struct){ x: (int){ 5 } } } f5: (struct){ out: (struct){ x: (int){ 6 } } } f6: (struct){ out: (struct){ x: (int){ 7 } } } f7: (struct){ out: (struct){ x: (int){ 8 } } } f8: (struct){ out: (struct){ x: (int){ 9 } } } } weave: (struct){ f: (struct){ out: (_|_){ // [cycle] cycle error: // ./in.cue:77:8 } in: (_|_){ // [incomplete] weave.f.in: undefined field: out: // ./in.cue:78:14 } ref: (struct){ } } f8: (struct){ out: (int){ 16 } in: (int){ 15 } ref: (struct){ out: (int){ 14 } in: (int){ 13 } ref: (struct){ out: (int){ 12 } in: (int){ 11 } ref: (struct){ out: (int){ 10 } in: (int){ 9 } ref: (struct){ out: (int){ 8 } in: (int){ 7 } ref: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } } } } } } } f7: (struct){ out: (int){ 14 } in: (int){ 13 } ref: (struct){ out: (int){ 12 } in: (int){ 11 } ref: (struct){ out: (int){ 10 } in: (int){ 9 } ref: (struct){ out: (int){ 8 } in: (int){ 7 } ref: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } } } } } } f6: (struct){ out: (int){ 12 } in: (int){ 11 } ref: (struct){ out: (int){ 10 } in: (int){ 9 } ref: (struct){ out: (int){ 8 } in: (int){ 7 } ref: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } } } } } f5: (struct){ out: (int){ 10 } in: (int){ 9 } ref: (struct){ out: (int){ 8 } in: (int){ 7 } ref: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } } } } f4: (struct){ out: (int){ 8 } in: (int){ 7 } ref: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } } } f3: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } } f2: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ out: (int){ 2 } } } f1: (struct){ out: (int){ 2 } } } weaveExtraField: (struct){ f: (struct){ out: (_|_){ // [cycle] cycle error: // ./in.cue:96:8 } in: (_|_){ // [incomplete] weaveExtraField.f.in: undefined field: out: // ./in.cue:97:14 } ref: (struct){ y: (int){ 4 } } } f8: (struct){ out: (int){ 16 } in: (int){ 15 } ref: (struct){ y: (int){ 4 } out: (int){ 14 } in: (int){ 13 } ref: (struct){ y: (int){ 4 } out: (int){ 12 } in: (int){ 11 } ref: (struct){ y: (int){ 4 } out: (int){ 10 } in: (int){ 9 } ref: (struct){ y: (int){ 4 } out: (int){ 8 } in: (int){ 7 } ref: (struct){ y: (int){ 4 } out: (int){ 6 } in: (int){ 5 } ref: (struct){ y: (int){ 4 } out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } } } } } } } f7: (struct){ out: (int){ 14 } in: (int){ 13 } ref: (struct){ y: (int){ 4 } out: (int){ 12 } in: (int){ 11 } ref: (struct){ y: (int){ 4 } out: (int){ 10 } in: (int){ 9 } ref: (struct){ y: (int){ 4 } out: (int){ 8 } in: (int){ 7 } ref: (struct){ y: (int){ 4 } out: (int){ 6 } in: (int){ 5 } ref: (struct){ y: (int){ 4 } out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } } } } } } f6: (struct){ out: (int){ 12 } in: (int){ 11 } ref: (struct){ y: (int){ 4 } out: (int){ 10 } in: (int){ 9 } ref: (struct){ y: (int){ 4 } out: (int){ 8 } in: (int){ 7 } ref: (struct){ y: (int){ 4 } out: (int){ 6 } in: (int){ 5 } ref: (struct){ y: (int){ 4 } out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } } } } } f5: (struct){ out: (int){ 10 } in: (int){ 9 } ref: (struct){ y: (int){ 4 } out: (int){ 8 } in: (int){ 7 } ref: (struct){ y: (int){ 4 } out: (int){ 6 } in: (int){ 5 } ref: (struct){ y: (int){ 4 } out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } } } } f4: (struct){ out: (int){ 8 } in: (int){ 7 } ref: (struct){ y: (int){ 4 } out: (int){ 6 } in: (int){ 5 } ref: (struct){ y: (int){ 4 } out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } } } f3: (struct){ out: (int){ 6 } in: (int){ 5 } ref: (struct){ y: (int){ 4 } out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } } f2: (struct){ out: (int){ 4 } in: (int){ 3 } ref: (struct){ y: (int){ 4 } out: (int){ 2 } } } f1: (struct){ out: (int){ 2 } } } } -- out/compile -- --- in.cue { binexpr: { f1: { out: { x: 2 } } f2: { out: { x: (〈2;f1〉.out.x + 1) } } f3: { out: { x: (〈2;f2〉.out.x + 1) } } f4: { out: { x: (〈2;f3〉.out.x + 1) } } f5: { out: { x: (〈2;f4〉.out.x + 1) } } f6: { out: { x: (〈2;f5〉.out.x + 1) } } f7: { out: { x: (〈2;f6〉.out.x + 1) } } f8: { out: { x: (〈2;f7〉.out.x + 1) } } } parenthesized: { f1: { out: { x: 2 } } f2: { out: { x: (〈2;f1〉.out.x + 1) } } f3: { out: { x: (〈2;f2〉.out.x + 1) } } f4: { out: { x: (〈2;f3〉.out.x + 1) } } f5: { out: { x: (〈2;f4〉.out.x + 1) } } f6: { out: { x: (〈2;f5〉.out.x + 1) } } f7: { out: { x: (〈2;f6〉.out.x + 1) } } f8: { out: { x: (〈2;f7〉.out.x + 1) } } } embedded: { f1: { out: { x: 2 } } f2: { out: { x: ({ 〈3;f1〉.out }.x + 1) } } f3: { out: { x: ({ 〈3;f2〉.out }.x + 1) } } f4: { out: { x: ({ 〈3;f3〉.out }.x + 1) } } f5: { out: { x: ({ 〈3;f4〉.out }.x + 1) } } f6: { out: { x: ({ 〈3;f5〉.out }.x + 1) } } f7: { out: { x: ({ 〈3;f6〉.out }.x + 1) } } f8: { out: { x: ({ 〈3;f7〉.out }.x + 1) } } } embeddedWithEmpty: { f1: { out: { x: 2 } } f2: { out: { x: ({ (〈3;f1〉.out & {}) }.x + 1) } } f3: { out: { x: ({ (〈3;f2〉.out & {}) }.x + 1) } } f4: { out: { x: ({ (〈3;f3〉.out & {}) }.x + 1) } } f5: { out: { x: ({ (〈3;f4〉.out & {}) }.x + 1) } } f6: { out: { x: ({ (〈3;f5〉.out & {}) }.x + 1) } } f7: { out: { x: ({ (〈3;f6〉.out & {}) }.x + 1) } } f8: { out: { x: ({ (〈3;f7〉.out & {}) }.x + 1) } } } weave: { f: { out: (〈0;in〉 + 1) in: (〈1〉.ref.out + 1) ref: (_ & {}) } f8: (〈0;f〉 & { ref: 〈1;f7〉 }) f7: (〈0;f〉 & { ref: 〈1;f6〉 }) f6: (〈0;f〉 & { ref: 〈1;f5〉 }) f5: (〈0;f〉 & { ref: 〈1;f4〉 }) f4: (〈0;f〉 & { ref: 〈1;f3〉 }) f3: (〈0;f〉 & { ref: 〈1;f2〉 }) f2: (〈0;f〉 & { ref: 〈1;f1〉 }) f1: { out: 2 } } weaveExtraField: { f: { out: (〈0;in〉 + 1) in: (〈1〉.ref.out + 1) ref: { y: 4 } } f8: (〈0;f〉 & { ref: 〈1;f7〉 }) f7: (〈0;f〉 & { ref: 〈1;f6〉 }) f6: (〈0;f〉 & { ref: 〈1;f5〉 }) f5: (〈0;f〉 & { ref: 〈1;f4〉 }) f4: (〈0;f〉 & { ref: 〈1;f3〉 }) f3: (〈0;f〉 & { ref: 〈1;f2〉 }) f2: (〈0;f〉 & { ref: 〈1;f1〉 }) f1: { out: 2 } } } cue-lang-cue-db9cc73/cue/testdata/benchmarks/sort.txtar000066400000000000000000007477601474664451600233020ustar00rootroot00000000000000// NOTE: the performance of Sort is not measured by counters. The issues // of https://cuelang.org/issues/745 were mostly related to poor memory // management. -- stats.txt -- Leaks: 0 Freed: 7529 Reused: 7523 Allocs: 6 Retain: 1 Unifications: 7529 Conjuncts: 12154 Disjuncts: 7530 -- in.cue -- import "list" _a: [{name: 1}, {name: 3}, {name: 4}, {name: 5}, {name: 6}, {name: 7}, {name: 8}, {name: 9}, {name: 0}] _b: [_a, _a, _a, _a, _a, _a, _a, _a, _a, _a] _c: [_b, _b, _b, _b, _b, _b, _b, _b, _b, _b] out: list.Sort(list.FlattenN(_c, 4), {x: _, y: _, less: x.name < y.name}) -- out/compile -- --- in.cue { _a: [ { name: 1 }, { name: 3 }, { name: 4 }, { name: 5 }, { name: 6 }, { name: 7 }, { name: 8 }, { name: 9 }, { name: 0 }, ] _b: [ 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, 〈1;_a〉, ] _c: [ 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, 〈1;_b〉, ] out: 〈import;list〉.Sort(〈import;list〉.FlattenN(〈0;_c〉, 4), { x: _ y: _ less: (〈0;x〉.name < 〈0;y〉.name) }) } -- out/evalalpha -- (struct){ _a: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } _b: (#list){ 0: ~(_a) 1: ~(_a) 2: ~(_a) 3: ~(_a) 4: ~(_a) 5: ~(_a) 6: ~(_a) 7: ~(_a) 8: ~(_a) 9: ~(_a) } _c: (#list){ 0: ~(_b) 1: ~(_b) 2: ~(_b) 3: ~(_b) 4: ~(_b) 5: ~(_b) 6: ~(_b) 7: ~(_b) 8: ~(_b) 9: ~(_b) } out: (#list){ 0: ~(_a.8) 1: ~(_a.17) 2: ~(_a.26) 3: ~(_a.35) 4: ~(_a.44) 5: ~(_a.53) 6: ~(_a.62) 7: ~(_a.71) 8: ~(_a.80) 9: ~(_a.89) 10: ~(_a.98) 11: ~(_a.107) 12: ~(_a.116) 13: ~(_a.125) 14: ~(_a.134) 15: ~(_a.143) 16: ~(_a.152) 17: ~(_a.161) 18: ~(_a.170) 19: ~(_a.179) 20: ~(_a.188) 21: ~(_a.197) 22: ~(_a.206) 23: ~(_a.215) 24: ~(_a.224) 25: ~(_a.233) 26: ~(_a.242) 27: ~(_a.251) 28: ~(_a.260) 29: ~(_a.269) 30: ~(_a.278) 31: ~(_a.287) 32: ~(_a.296) 33: ~(_a.305) 34: ~(_a.314) 35: ~(_a.323) 36: ~(_a.332) 37: ~(_a.341) 38: ~(_a.350) 39: ~(_a.359) 40: ~(_a.368) 41: ~(_a.377) 42: ~(_a.386) 43: ~(_a.395) 44: ~(_a.404) 45: ~(_a.413) 46: ~(_a.422) 47: ~(_a.431) 48: ~(_a.440) 49: ~(_a.449) 50: ~(_a.458) 51: ~(_a.467) 52: ~(_a.476) 53: ~(_a.485) 54: ~(_a.494) 55: ~(_a.503) 56: ~(_a.512) 57: ~(_a.521) 58: ~(_a.530) 59: ~(_a.539) 60: ~(_a.548) 61: ~(_a.557) 62: ~(_a.566) 63: ~(_a.575) 64: ~(_a.584) 65: ~(_a.593) 66: ~(_a.602) 67: ~(_a.611) 68: ~(_a.620) 69: ~(_a.629) 70: ~(_a.638) 71: ~(_a.647) 72: ~(_a.656) 73: ~(_a.665) 74: ~(_a.674) 75: ~(_a.683) 76: ~(_a.692) 77: ~(_a.701) 78: ~(_a.710) 79: ~(_a.719) 80: ~(_a.728) 81: ~(_a.737) 82: ~(_a.746) 83: ~(_a.755) 84: ~(_a.764) 85: ~(_a.773) 86: ~(_a.782) 87: ~(_a.791) 88: ~(_a.800) 89: ~(_a.809) 90: ~(_a.818) 91: ~(_a.827) 92: ~(_a.836) 93: ~(_a.845) 94: ~(_a.854) 95: ~(_a.863) 96: ~(_a.872) 97: ~(_a.881) 98: ~(_a.890) 99: ~(_a.899) 100: ~(_a.0) 101: ~(_a.9) 102: ~(_a.18) 103: ~(_a.27) 104: ~(_a.36) 105: ~(_a.45) 106: ~(_a.54) 107: ~(_a.63) 108: ~(_a.72) 109: ~(_a.81) 110: ~(_a.90) 111: ~(_a.99) 112: ~(_a.108) 113: ~(_a.117) 114: ~(_a.126) 115: ~(_a.135) 116: ~(_a.144) 117: ~(_a.153) 118: ~(_a.162) 119: ~(_a.171) 120: ~(_a.180) 121: ~(_a.189) 122: ~(_a.198) 123: ~(_a.207) 124: ~(_a.216) 125: ~(_a.225) 126: ~(_a.234) 127: ~(_a.243) 128: ~(_a.252) 129: ~(_a.261) 130: ~(_a.270) 131: ~(_a.279) 132: ~(_a.288) 133: ~(_a.297) 134: ~(_a.306) 135: ~(_a.315) 136: ~(_a.324) 137: ~(_a.333) 138: ~(_a.342) 139: ~(_a.351) 140: ~(_a.360) 141: ~(_a.369) 142: ~(_a.378) 143: ~(_a.387) 144: ~(_a.396) 145: ~(_a.405) 146: ~(_a.414) 147: ~(_a.423) 148: ~(_a.432) 149: ~(_a.441) 150: ~(_a.450) 151: ~(_a.459) 152: ~(_a.468) 153: ~(_a.477) 154: ~(_a.486) 155: ~(_a.495) 156: ~(_a.504) 157: ~(_a.513) 158: ~(_a.522) 159: ~(_a.531) 160: ~(_a.540) 161: ~(_a.549) 162: ~(_a.558) 163: ~(_a.567) 164: ~(_a.576) 165: ~(_a.585) 166: ~(_a.594) 167: ~(_a.603) 168: ~(_a.612) 169: ~(_a.621) 170: ~(_a.630) 171: ~(_a.639) 172: ~(_a.648) 173: ~(_a.657) 174: ~(_a.666) 175: ~(_a.675) 176: ~(_a.684) 177: ~(_a.693) 178: ~(_a.702) 179: ~(_a.711) 180: ~(_a.720) 181: ~(_a.729) 182: ~(_a.738) 183: ~(_a.747) 184: ~(_a.756) 185: ~(_a.765) 186: ~(_a.774) 187: ~(_a.783) 188: ~(_a.792) 189: ~(_a.801) 190: ~(_a.810) 191: ~(_a.819) 192: ~(_a.828) 193: ~(_a.837) 194: ~(_a.846) 195: ~(_a.855) 196: ~(_a.864) 197: ~(_a.873) 198: ~(_a.882) 199: ~(_a.891) 200: ~(_a.1) 201: ~(_a.10) 202: ~(_a.19) 203: ~(_a.28) 204: ~(_a.37) 205: ~(_a.46) 206: ~(_a.55) 207: ~(_a.64) 208: ~(_a.73) 209: ~(_a.82) 210: ~(_a.91) 211: ~(_a.100) 212: ~(_a.109) 213: ~(_a.118) 214: ~(_a.127) 215: ~(_a.136) 216: ~(_a.145) 217: ~(_a.154) 218: ~(_a.163) 219: ~(_a.172) 220: ~(_a.181) 221: ~(_a.190) 222: ~(_a.199) 223: ~(_a.208) 224: ~(_a.217) 225: ~(_a.226) 226: ~(_a.235) 227: ~(_a.244) 228: ~(_a.253) 229: ~(_a.262) 230: ~(_a.271) 231: ~(_a.280) 232: ~(_a.289) 233: ~(_a.298) 234: ~(_a.307) 235: ~(_a.316) 236: ~(_a.325) 237: ~(_a.334) 238: ~(_a.343) 239: ~(_a.352) 240: ~(_a.361) 241: ~(_a.370) 242: ~(_a.379) 243: ~(_a.388) 244: ~(_a.397) 245: ~(_a.406) 246: ~(_a.415) 247: ~(_a.424) 248: ~(_a.433) 249: ~(_a.442) 250: ~(_a.451) 251: ~(_a.460) 252: ~(_a.469) 253: ~(_a.478) 254: ~(_a.487) 255: ~(_a.496) 256: ~(_a.505) 257: ~(_a.514) 258: ~(_a.523) 259: ~(_a.532) 260: ~(_a.541) 261: ~(_a.550) 262: ~(_a.559) 263: ~(_a.568) 264: ~(_a.577) 265: ~(_a.586) 266: ~(_a.595) 267: ~(_a.604) 268: ~(_a.613) 269: ~(_a.622) 270: ~(_a.631) 271: ~(_a.640) 272: ~(_a.649) 273: ~(_a.658) 274: ~(_a.667) 275: ~(_a.676) 276: ~(_a.685) 277: ~(_a.694) 278: ~(_a.703) 279: ~(_a.712) 280: ~(_a.721) 281: ~(_a.730) 282: ~(_a.739) 283: ~(_a.748) 284: ~(_a.757) 285: ~(_a.766) 286: ~(_a.775) 287: ~(_a.784) 288: ~(_a.793) 289: ~(_a.802) 290: ~(_a.811) 291: ~(_a.820) 292: ~(_a.829) 293: ~(_a.838) 294: ~(_a.847) 295: ~(_a.856) 296: ~(_a.865) 297: ~(_a.874) 298: ~(_a.883) 299: ~(_a.892) 300: ~(_a.2) 301: ~(_a.11) 302: ~(_a.20) 303: ~(_a.29) 304: ~(_a.38) 305: ~(_a.47) 306: ~(_a.56) 307: ~(_a.65) 308: ~(_a.74) 309: ~(_a.83) 310: ~(_a.92) 311: ~(_a.101) 312: ~(_a.110) 313: ~(_a.119) 314: ~(_a.128) 315: ~(_a.137) 316: ~(_a.146) 317: ~(_a.155) 318: ~(_a.164) 319: ~(_a.173) 320: ~(_a.182) 321: ~(_a.191) 322: ~(_a.200) 323: ~(_a.209) 324: ~(_a.218) 325: ~(_a.227) 326: ~(_a.236) 327: ~(_a.245) 328: ~(_a.254) 329: ~(_a.263) 330: ~(_a.272) 331: ~(_a.281) 332: ~(_a.290) 333: ~(_a.299) 334: ~(_a.308) 335: ~(_a.317) 336: ~(_a.326) 337: ~(_a.335) 338: ~(_a.344) 339: ~(_a.353) 340: ~(_a.362) 341: ~(_a.371) 342: ~(_a.380) 343: ~(_a.389) 344: ~(_a.398) 345: ~(_a.407) 346: ~(_a.416) 347: ~(_a.425) 348: ~(_a.434) 349: ~(_a.443) 350: ~(_a.452) 351: ~(_a.461) 352: ~(_a.470) 353: ~(_a.479) 354: ~(_a.488) 355: ~(_a.497) 356: ~(_a.506) 357: ~(_a.515) 358: ~(_a.524) 359: ~(_a.533) 360: ~(_a.542) 361: ~(_a.551) 362: ~(_a.560) 363: ~(_a.569) 364: ~(_a.578) 365: ~(_a.587) 366: ~(_a.596) 367: ~(_a.605) 368: ~(_a.614) 369: ~(_a.623) 370: ~(_a.632) 371: ~(_a.641) 372: ~(_a.650) 373: ~(_a.659) 374: ~(_a.668) 375: ~(_a.677) 376: ~(_a.686) 377: ~(_a.695) 378: ~(_a.704) 379: ~(_a.713) 380: ~(_a.722) 381: ~(_a.731) 382: ~(_a.740) 383: ~(_a.749) 384: ~(_a.758) 385: ~(_a.767) 386: ~(_a.776) 387: ~(_a.785) 388: ~(_a.794) 389: ~(_a.803) 390: ~(_a.812) 391: ~(_a.821) 392: ~(_a.830) 393: ~(_a.839) 394: ~(_a.848) 395: ~(_a.857) 396: ~(_a.866) 397: ~(_a.875) 398: ~(_a.884) 399: ~(_a.893) 400: ~(_a.3) 401: ~(_a.12) 402: ~(_a.21) 403: ~(_a.30) 404: ~(_a.39) 405: ~(_a.48) 406: ~(_a.57) 407: ~(_a.66) 408: ~(_a.75) 409: ~(_a.84) 410: ~(_a.93) 411: ~(_a.102) 412: ~(_a.111) 413: ~(_a.120) 414: ~(_a.129) 415: ~(_a.138) 416: ~(_a.147) 417: ~(_a.156) 418: ~(_a.165) 419: ~(_a.174) 420: ~(_a.183) 421: ~(_a.192) 422: ~(_a.201) 423: ~(_a.210) 424: ~(_a.219) 425: ~(_a.228) 426: ~(_a.237) 427: ~(_a.246) 428: ~(_a.255) 429: ~(_a.264) 430: ~(_a.273) 431: ~(_a.282) 432: ~(_a.291) 433: ~(_a.300) 434: ~(_a.309) 435: ~(_a.318) 436: ~(_a.327) 437: ~(_a.336) 438: ~(_a.345) 439: ~(_a.354) 440: ~(_a.363) 441: ~(_a.372) 442: ~(_a.381) 443: ~(_a.390) 444: ~(_a.399) 445: ~(_a.408) 446: ~(_a.417) 447: ~(_a.426) 448: ~(_a.435) 449: ~(_a.444) 450: ~(_a.453) 451: ~(_a.462) 452: ~(_a.471) 453: ~(_a.480) 454: ~(_a.489) 455: ~(_a.498) 456: ~(_a.507) 457: ~(_a.516) 458: ~(_a.525) 459: ~(_a.534) 460: ~(_a.543) 461: ~(_a.552) 462: ~(_a.561) 463: ~(_a.570) 464: ~(_a.579) 465: ~(_a.588) 466: ~(_a.597) 467: ~(_a.606) 468: ~(_a.615) 469: ~(_a.624) 470: ~(_a.633) 471: ~(_a.642) 472: ~(_a.651) 473: ~(_a.660) 474: ~(_a.669) 475: ~(_a.678) 476: ~(_a.687) 477: ~(_a.696) 478: ~(_a.705) 479: ~(_a.714) 480: ~(_a.723) 481: ~(_a.732) 482: ~(_a.741) 483: ~(_a.750) 484: ~(_a.759) 485: ~(_a.768) 486: ~(_a.777) 487: ~(_a.786) 488: ~(_a.795) 489: ~(_a.804) 490: ~(_a.813) 491: ~(_a.822) 492: ~(_a.831) 493: ~(_a.840) 494: ~(_a.849) 495: ~(_a.858) 496: ~(_a.867) 497: ~(_a.876) 498: ~(_a.885) 499: ~(_a.894) 500: ~(_a.4) 501: ~(_a.13) 502: ~(_a.22) 503: ~(_a.31) 504: ~(_a.40) 505: ~(_a.49) 506: ~(_a.58) 507: ~(_a.67) 508: ~(_a.76) 509: ~(_a.85) 510: ~(_a.94) 511: ~(_a.103) 512: ~(_a.112) 513: ~(_a.121) 514: ~(_a.130) 515: ~(_a.139) 516: ~(_a.148) 517: ~(_a.157) 518: ~(_a.166) 519: ~(_a.175) 520: ~(_a.184) 521: ~(_a.193) 522: ~(_a.202) 523: ~(_a.211) 524: ~(_a.220) 525: ~(_a.229) 526: ~(_a.238) 527: ~(_a.247) 528: ~(_a.256) 529: ~(_a.265) 530: ~(_a.274) 531: ~(_a.283) 532: ~(_a.292) 533: ~(_a.301) 534: ~(_a.310) 535: ~(_a.319) 536: ~(_a.328) 537: ~(_a.337) 538: ~(_a.346) 539: ~(_a.355) 540: ~(_a.364) 541: ~(_a.373) 542: ~(_a.382) 543: ~(_a.391) 544: ~(_a.400) 545: ~(_a.409) 546: ~(_a.418) 547: ~(_a.427) 548: ~(_a.436) 549: ~(_a.445) 550: ~(_a.454) 551: ~(_a.463) 552: ~(_a.472) 553: ~(_a.481) 554: ~(_a.490) 555: ~(_a.499) 556: ~(_a.508) 557: ~(_a.517) 558: ~(_a.526) 559: ~(_a.535) 560: ~(_a.544) 561: ~(_a.553) 562: ~(_a.562) 563: ~(_a.571) 564: ~(_a.580) 565: ~(_a.589) 566: ~(_a.598) 567: ~(_a.607) 568: ~(_a.616) 569: ~(_a.625) 570: ~(_a.634) 571: ~(_a.643) 572: ~(_a.652) 573: ~(_a.661) 574: ~(_a.670) 575: ~(_a.679) 576: ~(_a.688) 577: ~(_a.697) 578: ~(_a.706) 579: ~(_a.715) 580: ~(_a.724) 581: ~(_a.733) 582: ~(_a.742) 583: ~(_a.751) 584: ~(_a.760) 585: ~(_a.769) 586: ~(_a.778) 587: ~(_a.787) 588: ~(_a.796) 589: ~(_a.805) 590: ~(_a.814) 591: ~(_a.823) 592: ~(_a.832) 593: ~(_a.841) 594: ~(_a.850) 595: ~(_a.859) 596: ~(_a.868) 597: ~(_a.877) 598: ~(_a.886) 599: ~(_a.895) 600: ~(_a.5) 601: ~(_a.14) 602: ~(_a.23) 603: ~(_a.32) 604: ~(_a.41) 605: ~(_a.50) 606: ~(_a.59) 607: ~(_a.68) 608: ~(_a.77) 609: ~(_a.86) 610: ~(_a.95) 611: ~(_a.104) 612: ~(_a.113) 613: ~(_a.122) 614: ~(_a.131) 615: ~(_a.140) 616: ~(_a.149) 617: ~(_a.158) 618: ~(_a.167) 619: ~(_a.176) 620: ~(_a.185) 621: ~(_a.194) 622: ~(_a.203) 623: ~(_a.212) 624: ~(_a.221) 625: ~(_a.230) 626: ~(_a.239) 627: ~(_a.248) 628: ~(_a.257) 629: ~(_a.266) 630: ~(_a.275) 631: ~(_a.284) 632: ~(_a.293) 633: ~(_a.302) 634: ~(_a.311) 635: ~(_a.320) 636: ~(_a.329) 637: ~(_a.338) 638: ~(_a.347) 639: ~(_a.356) 640: ~(_a.365) 641: ~(_a.374) 642: ~(_a.383) 643: ~(_a.392) 644: ~(_a.401) 645: ~(_a.410) 646: ~(_a.419) 647: ~(_a.428) 648: ~(_a.437) 649: ~(_a.446) 650: ~(_a.455) 651: ~(_a.464) 652: ~(_a.473) 653: ~(_a.482) 654: ~(_a.491) 655: ~(_a.500) 656: ~(_a.509) 657: ~(_a.518) 658: ~(_a.527) 659: ~(_a.536) 660: ~(_a.545) 661: ~(_a.554) 662: ~(_a.563) 663: ~(_a.572) 664: ~(_a.581) 665: ~(_a.590) 666: ~(_a.599) 667: ~(_a.608) 668: ~(_a.617) 669: ~(_a.626) 670: ~(_a.635) 671: ~(_a.644) 672: ~(_a.653) 673: ~(_a.662) 674: ~(_a.671) 675: ~(_a.680) 676: ~(_a.689) 677: ~(_a.698) 678: ~(_a.707) 679: ~(_a.716) 680: ~(_a.725) 681: ~(_a.734) 682: ~(_a.743) 683: ~(_a.752) 684: ~(_a.761) 685: ~(_a.770) 686: ~(_a.779) 687: ~(_a.788) 688: ~(_a.797) 689: ~(_a.806) 690: ~(_a.815) 691: ~(_a.824) 692: ~(_a.833) 693: ~(_a.842) 694: ~(_a.851) 695: ~(_a.860) 696: ~(_a.869) 697: ~(_a.878) 698: ~(_a.887) 699: ~(_a.896) 700: ~(_a.6) 701: ~(_a.15) 702: ~(_a.24) 703: ~(_a.33) 704: ~(_a.42) 705: ~(_a.51) 706: ~(_a.60) 707: ~(_a.69) 708: ~(_a.78) 709: ~(_a.87) 710: ~(_a.96) 711: ~(_a.105) 712: ~(_a.114) 713: ~(_a.123) 714: ~(_a.132) 715: ~(_a.141) 716: ~(_a.150) 717: ~(_a.159) 718: ~(_a.168) 719: ~(_a.177) 720: ~(_a.186) 721: ~(_a.195) 722: ~(_a.204) 723: ~(_a.213) 724: ~(_a.222) 725: ~(_a.231) 726: ~(_a.240) 727: ~(_a.249) 728: ~(_a.258) 729: ~(_a.267) 730: ~(_a.276) 731: ~(_a.285) 732: ~(_a.294) 733: ~(_a.303) 734: ~(_a.312) 735: ~(_a.321) 736: ~(_a.330) 737: ~(_a.339) 738: ~(_a.348) 739: ~(_a.357) 740: ~(_a.366) 741: ~(_a.375) 742: ~(_a.384) 743: ~(_a.393) 744: ~(_a.402) 745: ~(_a.411) 746: ~(_a.420) 747: ~(_a.429) 748: ~(_a.438) 749: ~(_a.447) 750: ~(_a.456) 751: ~(_a.465) 752: ~(_a.474) 753: ~(_a.483) 754: ~(_a.492) 755: ~(_a.501) 756: ~(_a.510) 757: ~(_a.519) 758: ~(_a.528) 759: ~(_a.537) 760: ~(_a.546) 761: ~(_a.555) 762: ~(_a.564) 763: ~(_a.573) 764: ~(_a.582) 765: ~(_a.591) 766: ~(_a.600) 767: ~(_a.609) 768: ~(_a.618) 769: ~(_a.627) 770: ~(_a.636) 771: ~(_a.645) 772: ~(_a.654) 773: ~(_a.663) 774: ~(_a.672) 775: ~(_a.681) 776: ~(_a.690) 777: ~(_a.699) 778: ~(_a.708) 779: ~(_a.717) 780: ~(_a.726) 781: ~(_a.735) 782: ~(_a.744) 783: ~(_a.753) 784: ~(_a.762) 785: ~(_a.771) 786: ~(_a.780) 787: ~(_a.789) 788: ~(_a.798) 789: ~(_a.807) 790: ~(_a.816) 791: ~(_a.825) 792: ~(_a.834) 793: ~(_a.843) 794: ~(_a.852) 795: ~(_a.861) 796: ~(_a.870) 797: ~(_a.879) 798: ~(_a.888) 799: ~(_a.897) 800: ~(_a.7) 801: ~(_a.16) 802: ~(_a.25) 803: ~(_a.34) 804: ~(_a.43) 805: ~(_a.52) 806: ~(_a.61) 807: ~(_a.70) 808: ~(_a.79) 809: ~(_a.88) 810: ~(_a.97) 811: ~(_a.106) 812: ~(_a.115) 813: ~(_a.124) 814: ~(_a.133) 815: ~(_a.142) 816: ~(_a.151) 817: ~(_a.160) 818: ~(_a.169) 819: ~(_a.178) 820: ~(_a.187) 821: ~(_a.196) 822: ~(_a.205) 823: ~(_a.214) 824: ~(_a.223) 825: ~(_a.232) 826: ~(_a.241) 827: ~(_a.250) 828: ~(_a.259) 829: ~(_a.268) 830: ~(_a.277) 831: ~(_a.286) 832: ~(_a.295) 833: ~(_a.304) 834: ~(_a.313) 835: ~(_a.322) 836: ~(_a.331) 837: ~(_a.340) 838: ~(_a.349) 839: ~(_a.358) 840: ~(_a.367) 841: ~(_a.376) 842: ~(_a.385) 843: ~(_a.394) 844: ~(_a.403) 845: ~(_a.412) 846: ~(_a.421) 847: ~(_a.430) 848: ~(_a.439) 849: ~(_a.448) 850: ~(_a.457) 851: ~(_a.466) 852: ~(_a.475) 853: ~(_a.484) 854: ~(_a.493) 855: ~(_a.502) 856: ~(_a.511) 857: ~(_a.520) 858: ~(_a.529) 859: ~(_a.538) 860: ~(_a.547) 861: ~(_a.556) 862: ~(_a.565) 863: ~(_a.574) 864: ~(_a.583) 865: ~(_a.592) 866: ~(_a.601) 867: ~(_a.610) 868: ~(_a.619) 869: ~(_a.628) 870: ~(_a.637) 871: ~(_a.646) 872: ~(_a.655) 873: ~(_a.664) 874: ~(_a.673) 875: ~(_a.682) 876: ~(_a.691) 877: ~(_a.700) 878: ~(_a.709) 879: ~(_a.718) 880: ~(_a.727) 881: ~(_a.736) 882: ~(_a.745) 883: ~(_a.754) 884: ~(_a.763) 885: ~(_a.772) 886: ~(_a.781) 887: ~(_a.790) 888: ~(_a.799) 889: ~(_a.808) 890: ~(_a.817) 891: ~(_a.826) 892: ~(_a.835) 893: ~(_a.844) 894: ~(_a.853) 895: ~(_a.862) 896: ~(_a.871) 897: ~(_a.880) 898: ~(_a.889) 899: ~(_a.898) } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -29,5919 +29,929 @@ } } _b: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } + 0: ~(_a) + 1: ~(_a) + 2: ~(_a) + 3: ~(_a) + 4: ~(_a) + 5: ~(_a) + 6: ~(_a) + 7: ~(_a) + 8: ~(_a) + 9: ~(_a) } _c: (#list){ - 0: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 1: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 2: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 3: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 4: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 5: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 6: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 7: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 8: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } - 9: (#list){ - 0: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 1: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 2: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 3: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 4: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 5: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 6: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 7: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 8: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - 9: (#list){ - 0: (struct){ - name: (int){ 1 } - } - 1: (struct){ - name: (int){ 3 } - } - 2: (struct){ - name: (int){ 4 } - } - 3: (struct){ - name: (int){ 5 } - } - 4: (struct){ - name: (int){ 6 } - } - 5: (struct){ - name: (int){ 7 } - } - 6: (struct){ - name: (int){ 8 } - } - 7: (struct){ - name: (int){ 9 } - } - 8: (struct){ - name: (int){ 0 } - } - } - } + 0: ~(_b) + 1: ~(_b) + 2: ~(_b) + 3: ~(_b) + 4: ~(_b) + 5: ~(_b) + 6: ~(_b) + 7: ~(_b) + 8: ~(_b) + 9: ~(_b) } out: (#list){ - 0: (struct){ - name: (int){ 0 } - } - 1: (struct){ - name: (int){ 0 } - } - 2: (struct){ - name: (int){ 0 } - } - 3: (struct){ - name: (int){ 0 } - } - 4: (struct){ - name: (int){ 0 } - } - 5: (struct){ - name: (int){ 0 } - } - 6: (struct){ - name: (int){ 0 } - } - 7: (struct){ - name: (int){ 0 } - } - 8: (struct){ - name: (int){ 0 } - } - 9: (struct){ - name: (int){ 0 } - } - 10: (struct){ - name: (int){ 0 } - } - 11: (struct){ - name: (int){ 0 } - } - 12: (struct){ - name: (int){ 0 } - } - 13: (struct){ - name: (int){ 0 } - } - 14: (struct){ - name: (int){ 0 } - } - 15: (struct){ - name: (int){ 0 } - } - 16: (struct){ - name: (int){ 0 } - } - 17: (struct){ - name: (int){ 0 } - } - 18: (struct){ - name: (int){ 0 } - } - 19: (struct){ - name: (int){ 0 } - } - 20: (struct){ - name: (int){ 0 } - } - 21: (struct){ - name: (int){ 0 } - } - 22: (struct){ - name: (int){ 0 } - } - 23: (struct){ - name: (int){ 0 } - } - 24: (struct){ - name: (int){ 0 } - } - 25: (struct){ - name: (int){ 0 } - } - 26: (struct){ - name: (int){ 0 } - } - 27: (struct){ - name: (int){ 0 } - } - 28: (struct){ - name: (int){ 0 } - } - 29: (struct){ - name: (int){ 0 } - } - 30: (struct){ - name: (int){ 0 } - } - 31: (struct){ - name: (int){ 0 } - } - 32: (struct){ - name: (int){ 0 } - } - 33: (struct){ - name: (int){ 0 } - } - 34: (struct){ - name: (int){ 0 } - } - 35: (struct){ - name: (int){ 0 } - } - 36: (struct){ - name: (int){ 0 } - } - 37: (struct){ - name: (int){ 0 } - } - 38: (struct){ - name: (int){ 0 } - } - 39: (struct){ - name: (int){ 0 } - } - 40: (struct){ - name: (int){ 0 } - } - 41: (struct){ - name: (int){ 0 } - } - 42: (struct){ - name: (int){ 0 } - } - 43: (struct){ - name: (int){ 0 } - } - 44: (struct){ - name: (int){ 0 } - } - 45: (struct){ - name: (int){ 0 } - } - 46: (struct){ - name: (int){ 0 } - } - 47: (struct){ - name: (int){ 0 } - } - 48: (struct){ - name: (int){ 0 } - } - 49: (struct){ - name: (int){ 0 } - } - 50: (struct){ - name: (int){ 0 } - } - 51: (struct){ - name: (int){ 0 } - } - 52: (struct){ - name: (int){ 0 } - } - 53: (struct){ - name: (int){ 0 } - } - 54: (struct){ - name: (int){ 0 } - } - 55: (struct){ - name: (int){ 0 } - } - 56: (struct){ - name: (int){ 0 } - } - 57: (struct){ - name: (int){ 0 } - } - 58: (struct){ - name: (int){ 0 } - } - 59: (struct){ - name: (int){ 0 } - } - 60: (struct){ - name: (int){ 0 } - } - 61: (struct){ - name: (int){ 0 } - } - 62: (struct){ - name: (int){ 0 } - } - 63: (struct){ - name: (int){ 0 } - } - 64: (struct){ - name: (int){ 0 } - } - 65: (struct){ - name: (int){ 0 } - } - 66: (struct){ - name: (int){ 0 } - } - 67: (struct){ - name: (int){ 0 } - } - 68: (struct){ - name: (int){ 0 } - } - 69: (struct){ - name: (int){ 0 } - } - 70: (struct){ - name: (int){ 0 } - } - 71: (struct){ - name: (int){ 0 } - } - 72: (struct){ - name: (int){ 0 } - } - 73: (struct){ - name: (int){ 0 } - } - 74: (struct){ - name: (int){ 0 } - } - 75: (struct){ - name: (int){ 0 } - } - 76: (struct){ - name: (int){ 0 } - } - 77: (struct){ - name: (int){ 0 } - } - 78: (struct){ - name: (int){ 0 } - } - 79: (struct){ - name: (int){ 0 } - } - 80: (struct){ - name: (int){ 0 } - } - 81: (struct){ - name: (int){ 0 } - } - 82: (struct){ - name: (int){ 0 } - } - 83: (struct){ - name: (int){ 0 } - } - 84: (struct){ - name: (int){ 0 } - } - 85: (struct){ - name: (int){ 0 } - } - 86: (struct){ - name: (int){ 0 } - } - 87: (struct){ - name: (int){ 0 } - } - 88: (struct){ - name: (int){ 0 } - } - 89: (struct){ - name: (int){ 0 } - } - 90: (struct){ - name: (int){ 0 } - } - 91: (struct){ - name: (int){ 0 } - } - 92: (struct){ - name: (int){ 0 } - } - 93: (struct){ - name: (int){ 0 } - } - 94: (struct){ - name: (int){ 0 } - } - 95: (struct){ - name: (int){ 0 } - } - 96: (struct){ - name: (int){ 0 } - } - 97: (struct){ - name: (int){ 0 } - } - 98: (struct){ - name: (int){ 0 } - } - 99: (struct){ - name: (int){ 0 } - } - 100: (struct){ - name: (int){ 1 } - } - 101: (struct){ - name: (int){ 1 } - } - 102: (struct){ - name: (int){ 1 } - } - 103: (struct){ - name: (int){ 1 } - } - 104: (struct){ - name: (int){ 1 } - } - 105: (struct){ - name: (int){ 1 } - } - 106: (struct){ - name: (int){ 1 } - } - 107: (struct){ - name: (int){ 1 } - } - 108: (struct){ - name: (int){ 1 } - } - 109: (struct){ - name: (int){ 1 } - } - 110: (struct){ - name: (int){ 1 } - } - 111: (struct){ - name: (int){ 1 } - } - 112: (struct){ - name: (int){ 1 } - } - 113: (struct){ - name: (int){ 1 } - } - 114: (struct){ - name: (int){ 1 } - } - 115: (struct){ - name: (int){ 1 } - } - 116: (struct){ - name: (int){ 1 } - } - 117: (struct){ - name: (int){ 1 } - } - 118: (struct){ - name: (int){ 1 } - } - 119: (struct){ - name: (int){ 1 } - } - 120: (struct){ - name: (int){ 1 } - } - 121: (struct){ - name: (int){ 1 } - } - 122: (struct){ - name: (int){ 1 } - } - 123: (struct){ - name: (int){ 1 } - } - 124: (struct){ - name: (int){ 1 } - } - 125: (struct){ - name: (int){ 1 } - } - 126: (struct){ - name: (int){ 1 } - } - 127: (struct){ - name: (int){ 1 } - } - 128: (struct){ - name: (int){ 1 } - } - 129: (struct){ - name: (int){ 1 } - } - 130: (struct){ - name: (int){ 1 } - } - 131: (struct){ - name: (int){ 1 } - } - 132: (struct){ - name: (int){ 1 } - } - 133: (struct){ - name: (int){ 1 } - } - 134: (struct){ - name: (int){ 1 } - } - 135: (struct){ - name: (int){ 1 } - } - 136: (struct){ - name: (int){ 1 } - } - 137: (struct){ - name: (int){ 1 } - } - 138: (struct){ - name: (int){ 1 } - } - 139: (struct){ - name: (int){ 1 } - } - 140: (struct){ - name: (int){ 1 } - } - 141: (struct){ - name: (int){ 1 } - } - 142: (struct){ - name: (int){ 1 } - } - 143: (struct){ - name: (int){ 1 } - } - 144: (struct){ - name: (int){ 1 } - } - 145: (struct){ - name: (int){ 1 } - } - 146: (struct){ - name: (int){ 1 } - } - 147: (struct){ - name: (int){ 1 } - } - 148: (struct){ - name: (int){ 1 } - } - 149: (struct){ - name: (int){ 1 } - } - 150: (struct){ - name: (int){ 1 } - } - 151: (struct){ - name: (int){ 1 } - } - 152: (struct){ - name: (int){ 1 } - } - 153: (struct){ - name: (int){ 1 } - } - 154: (struct){ - name: (int){ 1 } - } - 155: (struct){ - name: (int){ 1 } - } - 156: (struct){ - name: (int){ 1 } - } - 157: (struct){ - name: (int){ 1 } - } - 158: (struct){ - name: (int){ 1 } - } - 159: (struct){ - name: (int){ 1 } - } - 160: (struct){ - name: (int){ 1 } - } - 161: (struct){ - name: (int){ 1 } - } - 162: (struct){ - name: (int){ 1 } - } - 163: (struct){ - name: (int){ 1 } - } - 164: (struct){ - name: (int){ 1 } - } - 165: (struct){ - name: (int){ 1 } - } - 166: (struct){ - name: (int){ 1 } - } - 167: (struct){ - name: (int){ 1 } - } - 168: (struct){ - name: (int){ 1 } - } - 169: (struct){ - name: (int){ 1 } - } - 170: (struct){ - name: (int){ 1 } - } - 171: (struct){ - name: (int){ 1 } - } - 172: (struct){ - name: (int){ 1 } - } - 173: (struct){ - name: (int){ 1 } - } - 174: (struct){ - name: (int){ 1 } - } - 175: (struct){ - name: (int){ 1 } - } - 176: (struct){ - name: (int){ 1 } - } - 177: (struct){ - name: (int){ 1 } - } - 178: (struct){ - name: (int){ 1 } - } - 179: (struct){ - name: (int){ 1 } - } - 180: (struct){ - name: (int){ 1 } - } - 181: (struct){ - name: (int){ 1 } - } - 182: (struct){ - name: (int){ 1 } - } - 183: (struct){ - name: (int){ 1 } - } - 184: (struct){ - name: (int){ 1 } - } - 185: (struct){ - name: (int){ 1 } - } - 186: (struct){ - name: (int){ 1 } - } - 187: (struct){ - name: (int){ 1 } - } - 188: (struct){ - name: (int){ 1 } - } - 189: (struct){ - name: (int){ 1 } - } - 190: (struct){ - name: (int){ 1 } - } - 191: (struct){ - name: (int){ 1 } - } - 192: (struct){ - name: (int){ 1 } - } - 193: (struct){ - name: (int){ 1 } - } - 194: (struct){ - name: (int){ 1 } - } - 195: (struct){ - name: (int){ 1 } - } - 196: (struct){ - name: (int){ 1 } - } - 197: (struct){ - name: (int){ 1 } - } - 198: (struct){ - name: (int){ 1 } - } - 199: (struct){ - name: (int){ 1 } - } - 200: (struct){ - name: (int){ 3 } - } - 201: (struct){ - name: (int){ 3 } - } - 202: (struct){ - name: (int){ 3 } - } - 203: (struct){ - name: (int){ 3 } - } - 204: (struct){ - name: (int){ 3 } - } - 205: (struct){ - name: (int){ 3 } - } - 206: (struct){ - name: (int){ 3 } - } - 207: (struct){ - name: (int){ 3 } - } - 208: (struct){ - name: (int){ 3 } - } - 209: (struct){ - name: (int){ 3 } - } - 210: (struct){ - name: (int){ 3 } - } - 211: (struct){ - name: (int){ 3 } - } - 212: (struct){ - name: (int){ 3 } - } - 213: (struct){ - name: (int){ 3 } - } - 214: (struct){ - name: (int){ 3 } - } - 215: (struct){ - name: (int){ 3 } - } - 216: (struct){ - name: (int){ 3 } - } - 217: (struct){ - name: (int){ 3 } - } - 218: (struct){ - name: (int){ 3 } - } - 219: (struct){ - name: (int){ 3 } - } - 220: (struct){ - name: (int){ 3 } - } - 221: (struct){ - name: (int){ 3 } - } - 222: (struct){ - name: (int){ 3 } - } - 223: (struct){ - name: (int){ 3 } - } - 224: (struct){ - name: (int){ 3 } - } - 225: (struct){ - name: (int){ 3 } - } - 226: (struct){ - name: (int){ 3 } - } - 227: (struct){ - name: (int){ 3 } - } - 228: (struct){ - name: (int){ 3 } - } - 229: (struct){ - name: (int){ 3 } - } - 230: (struct){ - name: (int){ 3 } - } - 231: (struct){ - name: (int){ 3 } - } - 232: (struct){ - name: (int){ 3 } - } - 233: (struct){ - name: (int){ 3 } - } - 234: (struct){ - name: (int){ 3 } - } - 235: (struct){ - name: (int){ 3 } - } - 236: (struct){ - name: (int){ 3 } - } - 237: (struct){ - name: (int){ 3 } - } - 238: (struct){ - name: (int){ 3 } - } - 239: (struct){ - name: (int){ 3 } - } - 240: (struct){ - name: (int){ 3 } - } - 241: (struct){ - name: (int){ 3 } - } - 242: (struct){ - name: (int){ 3 } - } - 243: (struct){ - name: (int){ 3 } - } - 244: (struct){ - name: (int){ 3 } - } - 245: (struct){ - name: (int){ 3 } - } - 246: (struct){ - name: (int){ 3 } - } - 247: (struct){ - name: (int){ 3 } - } - 248: (struct){ - name: (int){ 3 } - } - 249: (struct){ - name: (int){ 3 } - } - 250: (struct){ - name: (int){ 3 } - } - 251: (struct){ - name: (int){ 3 } - } - 252: (struct){ - name: (int){ 3 } - } - 253: (struct){ - name: (int){ 3 } - } - 254: (struct){ - name: (int){ 3 } - } - 255: (struct){ - name: (int){ 3 } - } - 256: (struct){ - name: (int){ 3 } - } - 257: (struct){ - name: (int){ 3 } - } - 258: (struct){ - name: (int){ 3 } - } - 259: (struct){ - name: (int){ 3 } - } - 260: (struct){ - name: (int){ 3 } - } - 261: (struct){ - name: (int){ 3 } - } - 262: (struct){ - name: (int){ 3 } - } - 263: (struct){ - name: (int){ 3 } - } - 264: (struct){ - name: (int){ 3 } - } - 265: (struct){ - name: (int){ 3 } - } - 266: (struct){ - name: (int){ 3 } - } - 267: (struct){ - name: (int){ 3 } - } - 268: (struct){ - name: (int){ 3 } - } - 269: (struct){ - name: (int){ 3 } - } - 270: (struct){ - name: (int){ 3 } - } - 271: (struct){ - name: (int){ 3 } - } - 272: (struct){ - name: (int){ 3 } - } - 273: (struct){ - name: (int){ 3 } - } - 274: (struct){ - name: (int){ 3 } - } - 275: (struct){ - name: (int){ 3 } - } - 276: (struct){ - name: (int){ 3 } - } - 277: (struct){ - name: (int){ 3 } - } - 278: (struct){ - name: (int){ 3 } - } - 279: (struct){ - name: (int){ 3 } - } - 280: (struct){ - name: (int){ 3 } - } - 281: (struct){ - name: (int){ 3 } - } - 282: (struct){ - name: (int){ 3 } - } - 283: (struct){ - name: (int){ 3 } - } - 284: (struct){ - name: (int){ 3 } - } - 285: (struct){ - name: (int){ 3 } - } - 286: (struct){ - name: (int){ 3 } - } - 287: (struct){ - name: (int){ 3 } - } - 288: (struct){ - name: (int){ 3 } - } - 289: (struct){ - name: (int){ 3 } - } - 290: (struct){ - name: (int){ 3 } - } - 291: (struct){ - name: (int){ 3 } - } - 292: (struct){ - name: (int){ 3 } - } - 293: (struct){ - name: (int){ 3 } - } - 294: (struct){ - name: (int){ 3 } - } - 295: (struct){ - name: (int){ 3 } - } - 296: (struct){ - name: (int){ 3 } - } - 297: (struct){ - name: (int){ 3 } - } - 298: (struct){ - name: (int){ 3 } - } - 299: (struct){ - name: (int){ 3 } - } - 300: (struct){ - name: (int){ 4 } - } - 301: (struct){ - name: (int){ 4 } - } - 302: (struct){ - name: (int){ 4 } - } - 303: (struct){ - name: (int){ 4 } - } - 304: (struct){ - name: (int){ 4 } - } - 305: (struct){ - name: (int){ 4 } - } - 306: (struct){ - name: (int){ 4 } - } - 307: (struct){ - name: (int){ 4 } - } - 308: (struct){ - name: (int){ 4 } - } - 309: (struct){ - name: (int){ 4 } - } - 310: (struct){ - name: (int){ 4 } - } - 311: (struct){ - name: (int){ 4 } - } - 312: (struct){ - name: (int){ 4 } - } - 313: (struct){ - name: (int){ 4 } - } - 314: (struct){ - name: (int){ 4 } - } - 315: (struct){ - name: (int){ 4 } - } - 316: (struct){ - name: (int){ 4 } - } - 317: (struct){ - name: (int){ 4 } - } - 318: (struct){ - name: (int){ 4 } - } - 319: (struct){ - name: (int){ 4 } - } - 320: (struct){ - name: (int){ 4 } - } - 321: (struct){ - name: (int){ 4 } - } - 322: (struct){ - name: (int){ 4 } - } - 323: (struct){ - name: (int){ 4 } - } - 324: (struct){ - name: (int){ 4 } - } - 325: (struct){ - name: (int){ 4 } - } - 326: (struct){ - name: (int){ 4 } - } - 327: (struct){ - name: (int){ 4 } - } - 328: (struct){ - name: (int){ 4 } - } - 329: (struct){ - name: (int){ 4 } - } - 330: (struct){ - name: (int){ 4 } - } - 331: (struct){ - name: (int){ 4 } - } - 332: (struct){ - name: (int){ 4 } - } - 333: (struct){ - name: (int){ 4 } - } - 334: (struct){ - name: (int){ 4 } - } - 335: (struct){ - name: (int){ 4 } - } - 336: (struct){ - name: (int){ 4 } - } - 337: (struct){ - name: (int){ 4 } - } - 338: (struct){ - name: (int){ 4 } - } - 339: (struct){ - name: (int){ 4 } - } - 340: (struct){ - name: (int){ 4 } - } - 341: (struct){ - name: (int){ 4 } - } - 342: (struct){ - name: (int){ 4 } - } - 343: (struct){ - name: (int){ 4 } - } - 344: (struct){ - name: (int){ 4 } - } - 345: (struct){ - name: (int){ 4 } - } - 346: (struct){ - name: (int){ 4 } - } - 347: (struct){ - name: (int){ 4 } - } - 348: (struct){ - name: (int){ 4 } - } - 349: (struct){ - name: (int){ 4 } - } - 350: (struct){ - name: (int){ 4 } - } - 351: (struct){ - name: (int){ 4 } - } - 352: (struct){ - name: (int){ 4 } - } - 353: (struct){ - name: (int){ 4 } - } - 354: (struct){ - name: (int){ 4 } - } - 355: (struct){ - name: (int){ 4 } - } - 356: (struct){ - name: (int){ 4 } - } - 357: (struct){ - name: (int){ 4 } - } - 358: (struct){ - name: (int){ 4 } - } - 359: (struct){ - name: (int){ 4 } - } - 360: (struct){ - name: (int){ 4 } - } - 361: (struct){ - name: (int){ 4 } - } - 362: (struct){ - name: (int){ 4 } - } - 363: (struct){ - name: (int){ 4 } - } - 364: (struct){ - name: (int){ 4 } - } - 365: (struct){ - name: (int){ 4 } - } - 366: (struct){ - name: (int){ 4 } - } - 367: (struct){ - name: (int){ 4 } - } - 368: (struct){ - name: (int){ 4 } - } - 369: (struct){ - name: (int){ 4 } - } - 370: (struct){ - name: (int){ 4 } - } - 371: (struct){ - name: (int){ 4 } - } - 372: (struct){ - name: (int){ 4 } - } - 373: (struct){ - name: (int){ 4 } - } - 374: (struct){ - name: (int){ 4 } - } - 375: (struct){ - name: (int){ 4 } - } - 376: (struct){ - name: (int){ 4 } - } - 377: (struct){ - name: (int){ 4 } - } - 378: (struct){ - name: (int){ 4 } - } - 379: (struct){ - name: (int){ 4 } - } - 380: (struct){ - name: (int){ 4 } - } - 381: (struct){ - name: (int){ 4 } - } - 382: (struct){ - name: (int){ 4 } - } - 383: (struct){ - name: (int){ 4 } - } - 384: (struct){ - name: (int){ 4 } - } - 385: (struct){ - name: (int){ 4 } - } - 386: (struct){ - name: (int){ 4 } - } - 387: (struct){ - name: (int){ 4 } - } - 388: (struct){ - name: (int){ 4 } - } - 389: (struct){ - name: (int){ 4 } - } - 390: (struct){ - name: (int){ 4 } - } - 391: (struct){ - name: (int){ 4 } - } - 392: (struct){ - name: (int){ 4 } - } - 393: (struct){ - name: (int){ 4 } - } - 394: (struct){ - name: (int){ 4 } - } - 395: (struct){ - name: (int){ 4 } - } - 396: (struct){ - name: (int){ 4 } - } - 397: (struct){ - name: (int){ 4 } - } - 398: (struct){ - name: (int){ 4 } - } - 399: (struct){ - name: (int){ 4 } - } - 400: (struct){ - name: (int){ 5 } - } - 401: (struct){ - name: (int){ 5 } - } - 402: (struct){ - name: (int){ 5 } - } - 403: (struct){ - name: (int){ 5 } - } - 404: (struct){ - name: (int){ 5 } - } - 405: (struct){ - name: (int){ 5 } - } - 406: (struct){ - name: (int){ 5 } - } - 407: (struct){ - name: (int){ 5 } - } - 408: (struct){ - name: (int){ 5 } - } - 409: (struct){ - name: (int){ 5 } - } - 410: (struct){ - name: (int){ 5 } - } - 411: (struct){ - name: (int){ 5 } - } - 412: (struct){ - name: (int){ 5 } - } - 413: (struct){ - name: (int){ 5 } - } - 414: (struct){ - name: (int){ 5 } - } - 415: (struct){ - name: (int){ 5 } - } - 416: (struct){ - name: (int){ 5 } - } - 417: (struct){ - name: (int){ 5 } - } - 418: (struct){ - name: (int){ 5 } - } - 419: (struct){ - name: (int){ 5 } - } - 420: (struct){ - name: (int){ 5 } - } - 421: (struct){ - name: (int){ 5 } - } - 422: (struct){ - name: (int){ 5 } - } - 423: (struct){ - name: (int){ 5 } - } - 424: (struct){ - name: (int){ 5 } - } - 425: (struct){ - name: (int){ 5 } - } - 426: (struct){ - name: (int){ 5 } - } - 427: (struct){ - name: (int){ 5 } - } - 428: (struct){ - name: (int){ 5 } - } - 429: (struct){ - name: (int){ 5 } - } - 430: (struct){ - name: (int){ 5 } - } - 431: (struct){ - name: (int){ 5 } - } - 432: (struct){ - name: (int){ 5 } - } - 433: (struct){ - name: (int){ 5 } - } - 434: (struct){ - name: (int){ 5 } - } - 435: (struct){ - name: (int){ 5 } - } - 436: (struct){ - name: (int){ 5 } - } - 437: (struct){ - name: (int){ 5 } - } - 438: (struct){ - name: (int){ 5 } - } - 439: (struct){ - name: (int){ 5 } - } - 440: (struct){ - name: (int){ 5 } - } - 441: (struct){ - name: (int){ 5 } - } - 442: (struct){ - name: (int){ 5 } - } - 443: (struct){ - name: (int){ 5 } - } - 444: (struct){ - name: (int){ 5 } - } - 445: (struct){ - name: (int){ 5 } - } - 446: (struct){ - name: (int){ 5 } - } - 447: (struct){ - name: (int){ 5 } - } - 448: (struct){ - name: (int){ 5 } - } - 449: (struct){ - name: (int){ 5 } - } - 450: (struct){ - name: (int){ 5 } - } - 451: (struct){ - name: (int){ 5 } - } - 452: (struct){ - name: (int){ 5 } - } - 453: (struct){ - name: (int){ 5 } - } - 454: (struct){ - name: (int){ 5 } - } - 455: (struct){ - name: (int){ 5 } - } - 456: (struct){ - name: (int){ 5 } - } - 457: (struct){ - name: (int){ 5 } - } - 458: (struct){ - name: (int){ 5 } - } - 459: (struct){ - name: (int){ 5 } - } - 460: (struct){ - name: (int){ 5 } - } - 461: (struct){ - name: (int){ 5 } - } - 462: (struct){ - name: (int){ 5 } - } - 463: (struct){ - name: (int){ 5 } - } - 464: (struct){ - name: (int){ 5 } - } - 465: (struct){ - name: (int){ 5 } - } - 466: (struct){ - name: (int){ 5 } - } - 467: (struct){ - name: (int){ 5 } - } - 468: (struct){ - name: (int){ 5 } - } - 469: (struct){ - name: (int){ 5 } - } - 470: (struct){ - name: (int){ 5 } - } - 471: (struct){ - name: (int){ 5 } - } - 472: (struct){ - name: (int){ 5 } - } - 473: (struct){ - name: (int){ 5 } - } - 474: (struct){ - name: (int){ 5 } - } - 475: (struct){ - name: (int){ 5 } - } - 476: (struct){ - name: (int){ 5 } - } - 477: (struct){ - name: (int){ 5 } - } - 478: (struct){ - name: (int){ 5 } - } - 479: (struct){ - name: (int){ 5 } - } - 480: (struct){ - name: (int){ 5 } - } - 481: (struct){ - name: (int){ 5 } - } - 482: (struct){ - name: (int){ 5 } - } - 483: (struct){ - name: (int){ 5 } - } - 484: (struct){ - name: (int){ 5 } - } - 485: (struct){ - name: (int){ 5 } - } - 486: (struct){ - name: (int){ 5 } - } - 487: (struct){ - name: (int){ 5 } - } - 488: (struct){ - name: (int){ 5 } - } - 489: (struct){ - name: (int){ 5 } - } - 490: (struct){ - name: (int){ 5 } - } - 491: (struct){ - name: (int){ 5 } - } - 492: (struct){ - name: (int){ 5 } - } - 493: (struct){ - name: (int){ 5 } - } - 494: (struct){ - name: (int){ 5 } - } - 495: (struct){ - name: (int){ 5 } - } - 496: (struct){ - name: (int){ 5 } - } - 497: (struct){ - name: (int){ 5 } - } - 498: (struct){ - name: (int){ 5 } - } - 499: (struct){ - name: (int){ 5 } - } - 500: (struct){ - name: (int){ 6 } - } - 501: (struct){ - name: (int){ 6 } - } - 502: (struct){ - name: (int){ 6 } - } - 503: (struct){ - name: (int){ 6 } - } - 504: (struct){ - name: (int){ 6 } - } - 505: (struct){ - name: (int){ 6 } - } - 506: (struct){ - name: (int){ 6 } - } - 507: (struct){ - name: (int){ 6 } - } - 508: (struct){ - name: (int){ 6 } - } - 509: (struct){ - name: (int){ 6 } - } - 510: (struct){ - name: (int){ 6 } - } - 511: (struct){ - name: (int){ 6 } - } - 512: (struct){ - name: (int){ 6 } - } - 513: (struct){ - name: (int){ 6 } - } - 514: (struct){ - name: (int){ 6 } - } - 515: (struct){ - name: (int){ 6 } - } - 516: (struct){ - name: (int){ 6 } - } - 517: (struct){ - name: (int){ 6 } - } - 518: (struct){ - name: (int){ 6 } - } - 519: (struct){ - name: (int){ 6 } - } - 520: (struct){ - name: (int){ 6 } - } - 521: (struct){ - name: (int){ 6 } - } - 522: (struct){ - name: (int){ 6 } - } - 523: (struct){ - name: (int){ 6 } - } - 524: (struct){ - name: (int){ 6 } - } - 525: (struct){ - name: (int){ 6 } - } - 526: (struct){ - name: (int){ 6 } - } - 527: (struct){ - name: (int){ 6 } - } - 528: (struct){ - name: (int){ 6 } - } - 529: (struct){ - name: (int){ 6 } - } - 530: (struct){ - name: (int){ 6 } - } - 531: (struct){ - name: (int){ 6 } - } - 532: (struct){ - name: (int){ 6 } - } - 533: (struct){ - name: (int){ 6 } - } - 534: (struct){ - name: (int){ 6 } - } - 535: (struct){ - name: (int){ 6 } - } - 536: (struct){ - name: (int){ 6 } - } - 537: (struct){ - name: (int){ 6 } - } - 538: (struct){ - name: (int){ 6 } - } - 539: (struct){ - name: (int){ 6 } - } - 540: (struct){ - name: (int){ 6 } - } - 541: (struct){ - name: (int){ 6 } - } - 542: (struct){ - name: (int){ 6 } - } - 543: (struct){ - name: (int){ 6 } - } - 544: (struct){ - name: (int){ 6 } - } - 545: (struct){ - name: (int){ 6 } - } - 546: (struct){ - name: (int){ 6 } - } - 547: (struct){ - name: (int){ 6 } - } - 548: (struct){ - name: (int){ 6 } - } - 549: (struct){ - name: (int){ 6 } - } - 550: (struct){ - name: (int){ 6 } - } - 551: (struct){ - name: (int){ 6 } - } - 552: (struct){ - name: (int){ 6 } - } - 553: (struct){ - name: (int){ 6 } - } - 554: (struct){ - name: (int){ 6 } - } - 555: (struct){ - name: (int){ 6 } - } - 556: (struct){ - name: (int){ 6 } - } - 557: (struct){ - name: (int){ 6 } - } - 558: (struct){ - name: (int){ 6 } - } - 559: (struct){ - name: (int){ 6 } - } - 560: (struct){ - name: (int){ 6 } - } - 561: (struct){ - name: (int){ 6 } - } - 562: (struct){ - name: (int){ 6 } - } - 563: (struct){ - name: (int){ 6 } - } - 564: (struct){ - name: (int){ 6 } - } - 565: (struct){ - name: (int){ 6 } - } - 566: (struct){ - name: (int){ 6 } - } - 567: (struct){ - name: (int){ 6 } - } - 568: (struct){ - name: (int){ 6 } - } - 569: (struct){ - name: (int){ 6 } - } - 570: (struct){ - name: (int){ 6 } - } - 571: (struct){ - name: (int){ 6 } - } - 572: (struct){ - name: (int){ 6 } - } - 573: (struct){ - name: (int){ 6 } - } - 574: (struct){ - name: (int){ 6 } - } - 575: (struct){ - name: (int){ 6 } - } - 576: (struct){ - name: (int){ 6 } - } - 577: (struct){ - name: (int){ 6 } - } - 578: (struct){ - name: (int){ 6 } - } - 579: (struct){ - name: (int){ 6 } - } - 580: (struct){ - name: (int){ 6 } - } - 581: (struct){ - name: (int){ 6 } - } - 582: (struct){ - name: (int){ 6 } - } - 583: (struct){ - name: (int){ 6 } - } - 584: (struct){ - name: (int){ 6 } - } - 585: (struct){ - name: (int){ 6 } - } - 586: (struct){ - name: (int){ 6 } - } - 587: (struct){ - name: (int){ 6 } - } - 588: (struct){ - name: (int){ 6 } - } - 589: (struct){ - name: (int){ 6 } - } - 590: (struct){ - name: (int){ 6 } - } - 591: (struct){ - name: (int){ 6 } - } - 592: (struct){ - name: (int){ 6 } - } - 593: (struct){ - name: (int){ 6 } - } - 594: (struct){ - name: (int){ 6 } - } - 595: (struct){ - name: (int){ 6 } - } - 596: (struct){ - name: (int){ 6 } - } - 597: (struct){ - name: (int){ 6 } - } - 598: (struct){ - name: (int){ 6 } - } - 599: (struct){ - name: (int){ 6 } - } - 600: (struct){ - name: (int){ 7 } - } - 601: (struct){ - name: (int){ 7 } - } - 602: (struct){ - name: (int){ 7 } - } - 603: (struct){ - name: (int){ 7 } - } - 604: (struct){ - name: (int){ 7 } - } - 605: (struct){ - name: (int){ 7 } - } - 606: (struct){ - name: (int){ 7 } - } - 607: (struct){ - name: (int){ 7 } - } - 608: (struct){ - name: (int){ 7 } - } - 609: (struct){ - name: (int){ 7 } - } - 610: (struct){ - name: (int){ 7 } - } - 611: (struct){ - name: (int){ 7 } - } - 612: (struct){ - name: (int){ 7 } - } - 613: (struct){ - name: (int){ 7 } - } - 614: (struct){ - name: (int){ 7 } - } - 615: (struct){ - name: (int){ 7 } - } - 616: (struct){ - name: (int){ 7 } - } - 617: (struct){ - name: (int){ 7 } - } - 618: (struct){ - name: (int){ 7 } - } - 619: (struct){ - name: (int){ 7 } - } - 620: (struct){ - name: (int){ 7 } - } - 621: (struct){ - name: (int){ 7 } - } - 622: (struct){ - name: (int){ 7 } - } - 623: (struct){ - name: (int){ 7 } - } - 624: (struct){ - name: (int){ 7 } - } - 625: (struct){ - name: (int){ 7 } - } - 626: (struct){ - name: (int){ 7 } - } - 627: (struct){ - name: (int){ 7 } - } - 628: (struct){ - name: (int){ 7 } - } - 629: (struct){ - name: (int){ 7 } - } - 630: (struct){ - name: (int){ 7 } - } - 631: (struct){ - name: (int){ 7 } - } - 632: (struct){ - name: (int){ 7 } - } - 633: (struct){ - name: (int){ 7 } - } - 634: (struct){ - name: (int){ 7 } - } - 635: (struct){ - name: (int){ 7 } - } - 636: (struct){ - name: (int){ 7 } - } - 637: (struct){ - name: (int){ 7 } - } - 638: (struct){ - name: (int){ 7 } - } - 639: (struct){ - name: (int){ 7 } - } - 640: (struct){ - name: (int){ 7 } - } - 641: (struct){ - name: (int){ 7 } - } - 642: (struct){ - name: (int){ 7 } - } - 643: (struct){ - name: (int){ 7 } - } - 644: (struct){ - name: (int){ 7 } - } - 645: (struct){ - name: (int){ 7 } - } - 646: (struct){ - name: (int){ 7 } - } - 647: (struct){ - name: (int){ 7 } - } - 648: (struct){ - name: (int){ 7 } - } - 649: (struct){ - name: (int){ 7 } - } - 650: (struct){ - name: (int){ 7 } - } - 651: (struct){ - name: (int){ 7 } - } - 652: (struct){ - name: (int){ 7 } - } - 653: (struct){ - name: (int){ 7 } - } - 654: (struct){ - name: (int){ 7 } - } - 655: (struct){ - name: (int){ 7 } - } - 656: (struct){ - name: (int){ 7 } - } - 657: (struct){ - name: (int){ 7 } - } - 658: (struct){ - name: (int){ 7 } - } - 659: (struct){ - name: (int){ 7 } - } - 660: (struct){ - name: (int){ 7 } - } - 661: (struct){ - name: (int){ 7 } - } - 662: (struct){ - name: (int){ 7 } - } - 663: (struct){ - name: (int){ 7 } - } - 664: (struct){ - name: (int){ 7 } - } - 665: (struct){ - name: (int){ 7 } - } - 666: (struct){ - name: (int){ 7 } - } - 667: (struct){ - name: (int){ 7 } - } - 668: (struct){ - name: (int){ 7 } - } - 669: (struct){ - name: (int){ 7 } - } - 670: (struct){ - name: (int){ 7 } - } - 671: (struct){ - name: (int){ 7 } - } - 672: (struct){ - name: (int){ 7 } - } - 673: (struct){ - name: (int){ 7 } - } - 674: (struct){ - name: (int){ 7 } - } - 675: (struct){ - name: (int){ 7 } - } - 676: (struct){ - name: (int){ 7 } - } - 677: (struct){ - name: (int){ 7 } - } - 678: (struct){ - name: (int){ 7 } - } - 679: (struct){ - name: (int){ 7 } - } - 680: (struct){ - name: (int){ 7 } - } - 681: (struct){ - name: (int){ 7 } - } - 682: (struct){ - name: (int){ 7 } - } - 683: (struct){ - name: (int){ 7 } - } - 684: (struct){ - name: (int){ 7 } - } - 685: (struct){ - name: (int){ 7 } - } - 686: (struct){ - name: (int){ 7 } - } - 687: (struct){ - name: (int){ 7 } - } - 688: (struct){ - name: (int){ 7 } - } - 689: (struct){ - name: (int){ 7 } - } - 690: (struct){ - name: (int){ 7 } - } - 691: (struct){ - name: (int){ 7 } - } - 692: (struct){ - name: (int){ 7 } - } - 693: (struct){ - name: (int){ 7 } - } - 694: (struct){ - name: (int){ 7 } - } - 695: (struct){ - name: (int){ 7 } - } - 696: (struct){ - name: (int){ 7 } - } - 697: (struct){ - name: (int){ 7 } - } - 698: (struct){ - name: (int){ 7 } - } - 699: (struct){ - name: (int){ 7 } - } - 700: (struct){ - name: (int){ 8 } - } - 701: (struct){ - name: (int){ 8 } - } - 702: (struct){ - name: (int){ 8 } - } - 703: (struct){ - name: (int){ 8 } - } - 704: (struct){ - name: (int){ 8 } - } - 705: (struct){ - name: (int){ 8 } - } - 706: (struct){ - name: (int){ 8 } - } - 707: (struct){ - name: (int){ 8 } - } - 708: (struct){ - name: (int){ 8 } - } - 709: (struct){ - name: (int){ 8 } - } - 710: (struct){ - name: (int){ 8 } - } - 711: (struct){ - name: (int){ 8 } - } - 712: (struct){ - name: (int){ 8 } - } - 713: (struct){ - name: (int){ 8 } - } - 714: (struct){ - name: (int){ 8 } - } - 715: (struct){ - name: (int){ 8 } - } - 716: (struct){ - name: (int){ 8 } - } - 717: (struct){ - name: (int){ 8 } - } - 718: (struct){ - name: (int){ 8 } - } - 719: (struct){ - name: (int){ 8 } - } - 720: (struct){ - name: (int){ 8 } - } - 721: (struct){ - name: (int){ 8 } - } - 722: (struct){ - name: (int){ 8 } - } - 723: (struct){ - name: (int){ 8 } - } - 724: (struct){ - name: (int){ 8 } - } - 725: (struct){ - name: (int){ 8 } - } - 726: (struct){ - name: (int){ 8 } - } - 727: (struct){ - name: (int){ 8 } - } - 728: (struct){ - name: (int){ 8 } - } - 729: (struct){ - name: (int){ 8 } - } - 730: (struct){ - name: (int){ 8 } - } - 731: (struct){ - name: (int){ 8 } - } - 732: (struct){ - name: (int){ 8 } - } - 733: (struct){ - name: (int){ 8 } - } - 734: (struct){ - name: (int){ 8 } - } - 735: (struct){ - name: (int){ 8 } - } - 736: (struct){ - name: (int){ 8 } - } - 737: (struct){ - name: (int){ 8 } - } - 738: (struct){ - name: (int){ 8 } - } - 739: (struct){ - name: (int){ 8 } - } - 740: (struct){ - name: (int){ 8 } - } - 741: (struct){ - name: (int){ 8 } - } - 742: (struct){ - name: (int){ 8 } - } - 743: (struct){ - name: (int){ 8 } - } - 744: (struct){ - name: (int){ 8 } - } - 745: (struct){ - name: (int){ 8 } - } - 746: (struct){ - name: (int){ 8 } - } - 747: (struct){ - name: (int){ 8 } - } - 748: (struct){ - name: (int){ 8 } - } - 749: (struct){ - name: (int){ 8 } - } - 750: (struct){ - name: (int){ 8 } - } - 751: (struct){ - name: (int){ 8 } - } - 752: (struct){ - name: (int){ 8 } - } - 753: (struct){ - name: (int){ 8 } - } - 754: (struct){ - name: (int){ 8 } - } - 755: (struct){ - name: (int){ 8 } - } - 756: (struct){ - name: (int){ 8 } - } - 757: (struct){ - name: (int){ 8 } - } - 758: (struct){ - name: (int){ 8 } - } - 759: (struct){ - name: (int){ 8 } - } - 760: (struct){ - name: (int){ 8 } - } - 761: (struct){ - name: (int){ 8 } - } - 762: (struct){ - name: (int){ 8 } - } - 763: (struct){ - name: (int){ 8 } - } - 764: (struct){ - name: (int){ 8 } - } - 765: (struct){ - name: (int){ 8 } - } - 766: (struct){ - name: (int){ 8 } - } - 767: (struct){ - name: (int){ 8 } - } - 768: (struct){ - name: (int){ 8 } - } - 769: (struct){ - name: (int){ 8 } - } - 770: (struct){ - name: (int){ 8 } - } - 771: (struct){ - name: (int){ 8 } - } - 772: (struct){ - name: (int){ 8 } - } - 773: (struct){ - name: (int){ 8 } - } - 774: (struct){ - name: (int){ 8 } - } - 775: (struct){ - name: (int){ 8 } - } - 776: (struct){ - name: (int){ 8 } - } - 777: (struct){ - name: (int){ 8 } - } - 778: (struct){ - name: (int){ 8 } - } - 779: (struct){ - name: (int){ 8 } - } - 780: (struct){ - name: (int){ 8 } - } - 781: (struct){ - name: (int){ 8 } - } - 782: (struct){ - name: (int){ 8 } - } - 783: (struct){ - name: (int){ 8 } - } - 784: (struct){ - name: (int){ 8 } - } - 785: (struct){ - name: (int){ 8 } - } - 786: (struct){ - name: (int){ 8 } - } - 787: (struct){ - name: (int){ 8 } - } - 788: (struct){ - name: (int){ 8 } - } - 789: (struct){ - name: (int){ 8 } - } - 790: (struct){ - name: (int){ 8 } - } - 791: (struct){ - name: (int){ 8 } - } - 792: (struct){ - name: (int){ 8 } - } - 793: (struct){ - name: (int){ 8 } - } - 794: (struct){ - name: (int){ 8 } - } - 795: (struct){ - name: (int){ 8 } - } - 796: (struct){ - name: (int){ 8 } - } - 797: (struct){ - name: (int){ 8 } - } - 798: (struct){ - name: (int){ 8 } - } - 799: (struct){ - name: (int){ 8 } - } - 800: (struct){ - name: (int){ 9 } - } - 801: (struct){ - name: (int){ 9 } - } - 802: (struct){ - name: (int){ 9 } - } - 803: (struct){ - name: (int){ 9 } - } - 804: (struct){ - name: (int){ 9 } - } - 805: (struct){ - name: (int){ 9 } - } - 806: (struct){ - name: (int){ 9 } - } - 807: (struct){ - name: (int){ 9 } - } - 808: (struct){ - name: (int){ 9 } - } - 809: (struct){ - name: (int){ 9 } - } - 810: (struct){ - name: (int){ 9 } - } - 811: (struct){ - name: (int){ 9 } - } - 812: (struct){ - name: (int){ 9 } - } - 813: (struct){ - name: (int){ 9 } - } - 814: (struct){ - name: (int){ 9 } - } - 815: (struct){ - name: (int){ 9 } - } - 816: (struct){ - name: (int){ 9 } - } - 817: (struct){ - name: (int){ 9 } - } - 818: (struct){ - name: (int){ 9 } - } - 819: (struct){ - name: (int){ 9 } - } - 820: (struct){ - name: (int){ 9 } - } - 821: (struct){ - name: (int){ 9 } - } - 822: (struct){ - name: (int){ 9 } - } - 823: (struct){ - name: (int){ 9 } - } - 824: (struct){ - name: (int){ 9 } - } - 825: (struct){ - name: (int){ 9 } - } - 826: (struct){ - name: (int){ 9 } - } - 827: (struct){ - name: (int){ 9 } - } - 828: (struct){ - name: (int){ 9 } - } - 829: (struct){ - name: (int){ 9 } - } - 830: (struct){ - name: (int){ 9 } - } - 831: (struct){ - name: (int){ 9 } - } - 832: (struct){ - name: (int){ 9 } - } - 833: (struct){ - name: (int){ 9 } - } - 834: (struct){ - name: (int){ 9 } - } - 835: (struct){ - name: (int){ 9 } - } - 836: (struct){ - name: (int){ 9 } - } - 837: (struct){ - name: (int){ 9 } - } - 838: (struct){ - name: (int){ 9 } - } - 839: (struct){ - name: (int){ 9 } - } - 840: (struct){ - name: (int){ 9 } - } - 841: (struct){ - name: (int){ 9 } - } - 842: (struct){ - name: (int){ 9 } - } - 843: (struct){ - name: (int){ 9 } - } - 844: (struct){ - name: (int){ 9 } - } - 845: (struct){ - name: (int){ 9 } - } - 846: (struct){ - name: (int){ 9 } - } - 847: (struct){ - name: (int){ 9 } - } - 848: (struct){ - name: (int){ 9 } - } - 849: (struct){ - name: (int){ 9 } - } - 850: (struct){ - name: (int){ 9 } - } - 851: (struct){ - name: (int){ 9 } - } - 852: (struct){ - name: (int){ 9 } - } - 853: (struct){ - name: (int){ 9 } - } - 854: (struct){ - name: (int){ 9 } - } - 855: (struct){ - name: (int){ 9 } - } - 856: (struct){ - name: (int){ 9 } - } - 857: (struct){ - name: (int){ 9 } - } - 858: (struct){ - name: (int){ 9 } - } - 859: (struct){ - name: (int){ 9 } - } - 860: (struct){ - name: (int){ 9 } - } - 861: (struct){ - name: (int){ 9 } - } - 862: (struct){ - name: (int){ 9 } - } - 863: (struct){ - name: (int){ 9 } - } - 864: (struct){ - name: (int){ 9 } - } - 865: (struct){ - name: (int){ 9 } - } - 866: (struct){ - name: (int){ 9 } - } - 867: (struct){ - name: (int){ 9 } - } - 868: (struct){ - name: (int){ 9 } - } - 869: (struct){ - name: (int){ 9 } - } - 870: (struct){ - name: (int){ 9 } - } - 871: (struct){ - name: (int){ 9 } - } - 872: (struct){ - name: (int){ 9 } - } - 873: (struct){ - name: (int){ 9 } - } - 874: (struct){ - name: (int){ 9 } - } - 875: (struct){ - name: (int){ 9 } - } - 876: (struct){ - name: (int){ 9 } - } - 877: (struct){ - name: (int){ 9 } - } - 878: (struct){ - name: (int){ 9 } - } - 879: (struct){ - name: (int){ 9 } - } - 880: (struct){ - name: (int){ 9 } - } - 881: (struct){ - name: (int){ 9 } - } - 882: (struct){ - name: (int){ 9 } - } - 883: (struct){ - name: (int){ 9 } - } - 884: (struct){ - name: (int){ 9 } - } - 885: (struct){ - name: (int){ 9 } - } - 886: (struct){ - name: (int){ 9 } - } - 887: (struct){ - name: (int){ 9 } - } - 888: (struct){ - name: (int){ 9 } - } - 889: (struct){ - name: (int){ 9 } - } - 890: (struct){ - name: (int){ 9 } - } - 891: (struct){ - name: (int){ 9 } - } - 892: (struct){ - name: (int){ 9 } - } - 893: (struct){ - name: (int){ 9 } - } - 894: (struct){ - name: (int){ 9 } - } - 895: (struct){ - name: (int){ 9 } - } - 896: (struct){ - name: (int){ 9 } - } - 897: (struct){ - name: (int){ 9 } - } - 898: (struct){ - name: (int){ 9 } - } - 899: (struct){ - name: (int){ 9 } - } + 0: ~(_a.8) + 1: ~(_a.17) + 2: ~(_a.26) + 3: ~(_a.35) + 4: ~(_a.44) + 5: ~(_a.53) + 6: ~(_a.62) + 7: ~(_a.71) + 8: ~(_a.80) + 9: ~(_a.89) + 10: ~(_a.98) + 11: ~(_a.107) + 12: ~(_a.116) + 13: ~(_a.125) + 14: ~(_a.134) + 15: ~(_a.143) + 16: ~(_a.152) + 17: ~(_a.161) + 18: ~(_a.170) + 19: ~(_a.179) + 20: ~(_a.188) + 21: ~(_a.197) + 22: ~(_a.206) + 23: ~(_a.215) + 24: ~(_a.224) + 25: ~(_a.233) + 26: ~(_a.242) + 27: ~(_a.251) + 28: ~(_a.260) + 29: ~(_a.269) + 30: ~(_a.278) + 31: ~(_a.287) + 32: ~(_a.296) + 33: ~(_a.305) + 34: ~(_a.314) + 35: ~(_a.323) + 36: ~(_a.332) + 37: ~(_a.341) + 38: ~(_a.350) + 39: ~(_a.359) + 40: ~(_a.368) + 41: ~(_a.377) + 42: ~(_a.386) + 43: ~(_a.395) + 44: ~(_a.404) + 45: ~(_a.413) + 46: ~(_a.422) + 47: ~(_a.431) + 48: ~(_a.440) + 49: ~(_a.449) + 50: ~(_a.458) + 51: ~(_a.467) + 52: ~(_a.476) + 53: ~(_a.485) + 54: ~(_a.494) + 55: ~(_a.503) + 56: ~(_a.512) + 57: ~(_a.521) + 58: ~(_a.530) + 59: ~(_a.539) + 60: ~(_a.548) + 61: ~(_a.557) + 62: ~(_a.566) + 63: ~(_a.575) + 64: ~(_a.584) + 65: ~(_a.593) + 66: ~(_a.602) + 67: ~(_a.611) + 68: ~(_a.620) + 69: ~(_a.629) + 70: ~(_a.638) + 71: ~(_a.647) + 72: ~(_a.656) + 73: ~(_a.665) + 74: ~(_a.674) + 75: ~(_a.683) + 76: ~(_a.692) + 77: ~(_a.701) + 78: ~(_a.710) + 79: ~(_a.719) + 80: ~(_a.728) + 81: ~(_a.737) + 82: ~(_a.746) + 83: ~(_a.755) + 84: ~(_a.764) + 85: ~(_a.773) + 86: ~(_a.782) + 87: ~(_a.791) + 88: ~(_a.800) + 89: ~(_a.809) + 90: ~(_a.818) + 91: ~(_a.827) + 92: ~(_a.836) + 93: ~(_a.845) + 94: ~(_a.854) + 95: ~(_a.863) + 96: ~(_a.872) + 97: ~(_a.881) + 98: ~(_a.890) + 99: ~(_a.899) + 100: ~(_a.0) + 101: ~(_a.9) + 102: ~(_a.18) + 103: ~(_a.27) + 104: ~(_a.36) + 105: ~(_a.45) + 106: ~(_a.54) + 107: ~(_a.63) + 108: ~(_a.72) + 109: ~(_a.81) + 110: ~(_a.90) + 111: ~(_a.99) + 112: ~(_a.108) + 113: ~(_a.117) + 114: ~(_a.126) + 115: ~(_a.135) + 116: ~(_a.144) + 117: ~(_a.153) + 118: ~(_a.162) + 119: ~(_a.171) + 120: ~(_a.180) + 121: ~(_a.189) + 122: ~(_a.198) + 123: ~(_a.207) + 124: ~(_a.216) + 125: ~(_a.225) + 126: ~(_a.234) + 127: ~(_a.243) + 128: ~(_a.252) + 129: ~(_a.261) + 130: ~(_a.270) + 131: ~(_a.279) + 132: ~(_a.288) + 133: ~(_a.297) + 134: ~(_a.306) + 135: ~(_a.315) + 136: ~(_a.324) + 137: ~(_a.333) + 138: ~(_a.342) + 139: ~(_a.351) + 140: ~(_a.360) + 141: ~(_a.369) + 142: ~(_a.378) + 143: ~(_a.387) + 144: ~(_a.396) + 145: ~(_a.405) + 146: ~(_a.414) + 147: ~(_a.423) + 148: ~(_a.432) + 149: ~(_a.441) + 150: ~(_a.450) + 151: ~(_a.459) + 152: ~(_a.468) + 153: ~(_a.477) + 154: ~(_a.486) + 155: ~(_a.495) + 156: ~(_a.504) + 157: ~(_a.513) + 158: ~(_a.522) + 159: ~(_a.531) + 160: ~(_a.540) + 161: ~(_a.549) + 162: ~(_a.558) + 163: ~(_a.567) + 164: ~(_a.576) + 165: ~(_a.585) + 166: ~(_a.594) + 167: ~(_a.603) + 168: ~(_a.612) + 169: ~(_a.621) + 170: ~(_a.630) + 171: ~(_a.639) + 172: ~(_a.648) + 173: ~(_a.657) + 174: ~(_a.666) + 175: ~(_a.675) + 176: ~(_a.684) + 177: ~(_a.693) + 178: ~(_a.702) + 179: ~(_a.711) + 180: ~(_a.720) + 181: ~(_a.729) + 182: ~(_a.738) + 183: ~(_a.747) + 184: ~(_a.756) + 185: ~(_a.765) + 186: ~(_a.774) + 187: ~(_a.783) + 188: ~(_a.792) + 189: ~(_a.801) + 190: ~(_a.810) + 191: ~(_a.819) + 192: ~(_a.828) + 193: ~(_a.837) + 194: ~(_a.846) + 195: ~(_a.855) + 196: ~(_a.864) + 197: ~(_a.873) + 198: ~(_a.882) + 199: ~(_a.891) + 200: ~(_a.1) + 201: ~(_a.10) + 202: ~(_a.19) + 203: ~(_a.28) + 204: ~(_a.37) + 205: ~(_a.46) + 206: ~(_a.55) + 207: ~(_a.64) + 208: ~(_a.73) + 209: ~(_a.82) + 210: ~(_a.91) + 211: ~(_a.100) + 212: ~(_a.109) + 213: ~(_a.118) + 214: ~(_a.127) + 215: ~(_a.136) + 216: ~(_a.145) + 217: ~(_a.154) + 218: ~(_a.163) + 219: ~(_a.172) + 220: ~(_a.181) + 221: ~(_a.190) + 222: ~(_a.199) + 223: ~(_a.208) + 224: ~(_a.217) + 225: ~(_a.226) + 226: ~(_a.235) + 227: ~(_a.244) + 228: ~(_a.253) + 229: ~(_a.262) + 230: ~(_a.271) + 231: ~(_a.280) + 232: ~(_a.289) + 233: ~(_a.298) + 234: ~(_a.307) + 235: ~(_a.316) + 236: ~(_a.325) + 237: ~(_a.334) + 238: ~(_a.343) + 239: ~(_a.352) + 240: ~(_a.361) + 241: ~(_a.370) + 242: ~(_a.379) + 243: ~(_a.388) + 244: ~(_a.397) + 245: ~(_a.406) + 246: ~(_a.415) + 247: ~(_a.424) + 248: ~(_a.433) + 249: ~(_a.442) + 250: ~(_a.451) + 251: ~(_a.460) + 252: ~(_a.469) + 253: ~(_a.478) + 254: ~(_a.487) + 255: ~(_a.496) + 256: ~(_a.505) + 257: ~(_a.514) + 258: ~(_a.523) + 259: ~(_a.532) + 260: ~(_a.541) + 261: ~(_a.550) + 262: ~(_a.559) + 263: ~(_a.568) + 264: ~(_a.577) + 265: ~(_a.586) + 266: ~(_a.595) + 267: ~(_a.604) + 268: ~(_a.613) + 269: ~(_a.622) + 270: ~(_a.631) + 271: ~(_a.640) + 272: ~(_a.649) + 273: ~(_a.658) + 274: ~(_a.667) + 275: ~(_a.676) + 276: ~(_a.685) + 277: ~(_a.694) + 278: ~(_a.703) + 279: ~(_a.712) + 280: ~(_a.721) + 281: ~(_a.730) + 282: ~(_a.739) + 283: ~(_a.748) + 284: ~(_a.757) + 285: ~(_a.766) + 286: ~(_a.775) + 287: ~(_a.784) + 288: ~(_a.793) + 289: ~(_a.802) + 290: ~(_a.811) + 291: ~(_a.820) + 292: ~(_a.829) + 293: ~(_a.838) + 294: ~(_a.847) + 295: ~(_a.856) + 296: ~(_a.865) + 297: ~(_a.874) + 298: ~(_a.883) + 299: ~(_a.892) + 300: ~(_a.2) + 301: ~(_a.11) + 302: ~(_a.20) + 303: ~(_a.29) + 304: ~(_a.38) + 305: ~(_a.47) + 306: ~(_a.56) + 307: ~(_a.65) + 308: ~(_a.74) + 309: ~(_a.83) + 310: ~(_a.92) + 311: ~(_a.101) + 312: ~(_a.110) + 313: ~(_a.119) + 314: ~(_a.128) + 315: ~(_a.137) + 316: ~(_a.146) + 317: ~(_a.155) + 318: ~(_a.164) + 319: ~(_a.173) + 320: ~(_a.182) + 321: ~(_a.191) + 322: ~(_a.200) + 323: ~(_a.209) + 324: ~(_a.218) + 325: ~(_a.227) + 326: ~(_a.236) + 327: ~(_a.245) + 328: ~(_a.254) + 329: ~(_a.263) + 330: ~(_a.272) + 331: ~(_a.281) + 332: ~(_a.290) + 333: ~(_a.299) + 334: ~(_a.308) + 335: ~(_a.317) + 336: ~(_a.326) + 337: ~(_a.335) + 338: ~(_a.344) + 339: ~(_a.353) + 340: ~(_a.362) + 341: ~(_a.371) + 342: ~(_a.380) + 343: ~(_a.389) + 344: ~(_a.398) + 345: ~(_a.407) + 346: ~(_a.416) + 347: ~(_a.425) + 348: ~(_a.434) + 349: ~(_a.443) + 350: ~(_a.452) + 351: ~(_a.461) + 352: ~(_a.470) + 353: ~(_a.479) + 354: ~(_a.488) + 355: ~(_a.497) + 356: ~(_a.506) + 357: ~(_a.515) + 358: ~(_a.524) + 359: ~(_a.533) + 360: ~(_a.542) + 361: ~(_a.551) + 362: ~(_a.560) + 363: ~(_a.569) + 364: ~(_a.578) + 365: ~(_a.587) + 366: ~(_a.596) + 367: ~(_a.605) + 368: ~(_a.614) + 369: ~(_a.623) + 370: ~(_a.632) + 371: ~(_a.641) + 372: ~(_a.650) + 373: ~(_a.659) + 374: ~(_a.668) + 375: ~(_a.677) + 376: ~(_a.686) + 377: ~(_a.695) + 378: ~(_a.704) + 379: ~(_a.713) + 380: ~(_a.722) + 381: ~(_a.731) + 382: ~(_a.740) + 383: ~(_a.749) + 384: ~(_a.758) + 385: ~(_a.767) + 386: ~(_a.776) + 387: ~(_a.785) + 388: ~(_a.794) + 389: ~(_a.803) + 390: ~(_a.812) + 391: ~(_a.821) + 392: ~(_a.830) + 393: ~(_a.839) + 394: ~(_a.848) + 395: ~(_a.857) + 396: ~(_a.866) + 397: ~(_a.875) + 398: ~(_a.884) + 399: ~(_a.893) + 400: ~(_a.3) + 401: ~(_a.12) + 402: ~(_a.21) + 403: ~(_a.30) + 404: ~(_a.39) + 405: ~(_a.48) + 406: ~(_a.57) + 407: ~(_a.66) + 408: ~(_a.75) + 409: ~(_a.84) + 410: ~(_a.93) + 411: ~(_a.102) + 412: ~(_a.111) + 413: ~(_a.120) + 414: ~(_a.129) + 415: ~(_a.138) + 416: ~(_a.147) + 417: ~(_a.156) + 418: ~(_a.165) + 419: ~(_a.174) + 420: ~(_a.183) + 421: ~(_a.192) + 422: ~(_a.201) + 423: ~(_a.210) + 424: ~(_a.219) + 425: ~(_a.228) + 426: ~(_a.237) + 427: ~(_a.246) + 428: ~(_a.255) + 429: ~(_a.264) + 430: ~(_a.273) + 431: ~(_a.282) + 432: ~(_a.291) + 433: ~(_a.300) + 434: ~(_a.309) + 435: ~(_a.318) + 436: ~(_a.327) + 437: ~(_a.336) + 438: ~(_a.345) + 439: ~(_a.354) + 440: ~(_a.363) + 441: ~(_a.372) + 442: ~(_a.381) + 443: ~(_a.390) + 444: ~(_a.399) + 445: ~(_a.408) + 446: ~(_a.417) + 447: ~(_a.426) + 448: ~(_a.435) + 449: ~(_a.444) + 450: ~(_a.453) + 451: ~(_a.462) + 452: ~(_a.471) + 453: ~(_a.480) + 454: ~(_a.489) + 455: ~(_a.498) + 456: ~(_a.507) + 457: ~(_a.516) + 458: ~(_a.525) + 459: ~(_a.534) + 460: ~(_a.543) + 461: ~(_a.552) + 462: ~(_a.561) + 463: ~(_a.570) + 464: ~(_a.579) + 465: ~(_a.588) + 466: ~(_a.597) + 467: ~(_a.606) + 468: ~(_a.615) + 469: ~(_a.624) + 470: ~(_a.633) + 471: ~(_a.642) + 472: ~(_a.651) + 473: ~(_a.660) + 474: ~(_a.669) + 475: ~(_a.678) + 476: ~(_a.687) + 477: ~(_a.696) + 478: ~(_a.705) + 479: ~(_a.714) + 480: ~(_a.723) + 481: ~(_a.732) + 482: ~(_a.741) + 483: ~(_a.750) + 484: ~(_a.759) + 485: ~(_a.768) + 486: ~(_a.777) + 487: ~(_a.786) + 488: ~(_a.795) + 489: ~(_a.804) + 490: ~(_a.813) + 491: ~(_a.822) + 492: ~(_a.831) + 493: ~(_a.840) + 494: ~(_a.849) + 495: ~(_a.858) + 496: ~(_a.867) + 497: ~(_a.876) + 498: ~(_a.885) + 499: ~(_a.894) + 500: ~(_a.4) + 501: ~(_a.13) + 502: ~(_a.22) + 503: ~(_a.31) + 504: ~(_a.40) + 505: ~(_a.49) + 506: ~(_a.58) + 507: ~(_a.67) + 508: ~(_a.76) + 509: ~(_a.85) + 510: ~(_a.94) + 511: ~(_a.103) + 512: ~(_a.112) + 513: ~(_a.121) + 514: ~(_a.130) + 515: ~(_a.139) + 516: ~(_a.148) + 517: ~(_a.157) + 518: ~(_a.166) + 519: ~(_a.175) + 520: ~(_a.184) + 521: ~(_a.193) + 522: ~(_a.202) + 523: ~(_a.211) + 524: ~(_a.220) + 525: ~(_a.229) + 526: ~(_a.238) + 527: ~(_a.247) + 528: ~(_a.256) + 529: ~(_a.265) + 530: ~(_a.274) + 531: ~(_a.283) + 532: ~(_a.292) + 533: ~(_a.301) + 534: ~(_a.310) + 535: ~(_a.319) + 536: ~(_a.328) + 537: ~(_a.337) + 538: ~(_a.346) + 539: ~(_a.355) + 540: ~(_a.364) + 541: ~(_a.373) + 542: ~(_a.382) + 543: ~(_a.391) + 544: ~(_a.400) + 545: ~(_a.409) + 546: ~(_a.418) + 547: ~(_a.427) + 548: ~(_a.436) + 549: ~(_a.445) + 550: ~(_a.454) + 551: ~(_a.463) + 552: ~(_a.472) + 553: ~(_a.481) + 554: ~(_a.490) + 555: ~(_a.499) + 556: ~(_a.508) + 557: ~(_a.517) + 558: ~(_a.526) + 559: ~(_a.535) + 560: ~(_a.544) + 561: ~(_a.553) + 562: ~(_a.562) + 563: ~(_a.571) + 564: ~(_a.580) + 565: ~(_a.589) + 566: ~(_a.598) + 567: ~(_a.607) + 568: ~(_a.616) + 569: ~(_a.625) + 570: ~(_a.634) + 571: ~(_a.643) + 572: ~(_a.652) + 573: ~(_a.661) + 574: ~(_a.670) + 575: ~(_a.679) + 576: ~(_a.688) + 577: ~(_a.697) + 578: ~(_a.706) + 579: ~(_a.715) + 580: ~(_a.724) + 581: ~(_a.733) + 582: ~(_a.742) + 583: ~(_a.751) + 584: ~(_a.760) + 585: ~(_a.769) + 586: ~(_a.778) + 587: ~(_a.787) + 588: ~(_a.796) + 589: ~(_a.805) + 590: ~(_a.814) + 591: ~(_a.823) + 592: ~(_a.832) + 593: ~(_a.841) + 594: ~(_a.850) + 595: ~(_a.859) + 596: ~(_a.868) + 597: ~(_a.877) + 598: ~(_a.886) + 599: ~(_a.895) + 600: ~(_a.5) + 601: ~(_a.14) + 602: ~(_a.23) + 603: ~(_a.32) + 604: ~(_a.41) + 605: ~(_a.50) + 606: ~(_a.59) + 607: ~(_a.68) + 608: ~(_a.77) + 609: ~(_a.86) + 610: ~(_a.95) + 611: ~(_a.104) + 612: ~(_a.113) + 613: ~(_a.122) + 614: ~(_a.131) + 615: ~(_a.140) + 616: ~(_a.149) + 617: ~(_a.158) + 618: ~(_a.167) + 619: ~(_a.176) + 620: ~(_a.185) + 621: ~(_a.194) + 622: ~(_a.203) + 623: ~(_a.212) + 624: ~(_a.221) + 625: ~(_a.230) + 626: ~(_a.239) + 627: ~(_a.248) + 628: ~(_a.257) + 629: ~(_a.266) + 630: ~(_a.275) + 631: ~(_a.284) + 632: ~(_a.293) + 633: ~(_a.302) + 634: ~(_a.311) + 635: ~(_a.320) + 636: ~(_a.329) + 637: ~(_a.338) + 638: ~(_a.347) + 639: ~(_a.356) + 640: ~(_a.365) + 641: ~(_a.374) + 642: ~(_a.383) + 643: ~(_a.392) + 644: ~(_a.401) + 645: ~(_a.410) + 646: ~(_a.419) + 647: ~(_a.428) + 648: ~(_a.437) + 649: ~(_a.446) + 650: ~(_a.455) + 651: ~(_a.464) + 652: ~(_a.473) + 653: ~(_a.482) + 654: ~(_a.491) + 655: ~(_a.500) + 656: ~(_a.509) + 657: ~(_a.518) + 658: ~(_a.527) + 659: ~(_a.536) + 660: ~(_a.545) + 661: ~(_a.554) + 662: ~(_a.563) + 663: ~(_a.572) + 664: ~(_a.581) + 665: ~(_a.590) + 666: ~(_a.599) + 667: ~(_a.608) + 668: ~(_a.617) + 669: ~(_a.626) + 670: ~(_a.635) + 671: ~(_a.644) + 672: ~(_a.653) + 673: ~(_a.662) + 674: ~(_a.671) + 675: ~(_a.680) + 676: ~(_a.689) + 677: ~(_a.698) + 678: ~(_a.707) + 679: ~(_a.716) + 680: ~(_a.725) + 681: ~(_a.734) + 682: ~(_a.743) + 683: ~(_a.752) + 684: ~(_a.761) + 685: ~(_a.770) + 686: ~(_a.779) + 687: ~(_a.788) + 688: ~(_a.797) + 689: ~(_a.806) + 690: ~(_a.815) + 691: ~(_a.824) + 692: ~(_a.833) + 693: ~(_a.842) + 694: ~(_a.851) + 695: ~(_a.860) + 696: ~(_a.869) + 697: ~(_a.878) + 698: ~(_a.887) + 699: ~(_a.896) + 700: ~(_a.6) + 701: ~(_a.15) + 702: ~(_a.24) + 703: ~(_a.33) + 704: ~(_a.42) + 705: ~(_a.51) + 706: ~(_a.60) + 707: ~(_a.69) + 708: ~(_a.78) + 709: ~(_a.87) + 710: ~(_a.96) + 711: ~(_a.105) + 712: ~(_a.114) + 713: ~(_a.123) + 714: ~(_a.132) + 715: ~(_a.141) + 716: ~(_a.150) + 717: ~(_a.159) + 718: ~(_a.168) + 719: ~(_a.177) + 720: ~(_a.186) + 721: ~(_a.195) + 722: ~(_a.204) + 723: ~(_a.213) + 724: ~(_a.222) + 725: ~(_a.231) + 726: ~(_a.240) + 727: ~(_a.249) + 728: ~(_a.258) + 729: ~(_a.267) + 730: ~(_a.276) + 731: ~(_a.285) + 732: ~(_a.294) + 733: ~(_a.303) + 734: ~(_a.312) + 735: ~(_a.321) + 736: ~(_a.330) + 737: ~(_a.339) + 738: ~(_a.348) + 739: ~(_a.357) + 740: ~(_a.366) + 741: ~(_a.375) + 742: ~(_a.384) + 743: ~(_a.393) + 744: ~(_a.402) + 745: ~(_a.411) + 746: ~(_a.420) + 747: ~(_a.429) + 748: ~(_a.438) + 749: ~(_a.447) + 750: ~(_a.456) + 751: ~(_a.465) + 752: ~(_a.474) + 753: ~(_a.483) + 754: ~(_a.492) + 755: ~(_a.501) + 756: ~(_a.510) + 757: ~(_a.519) + 758: ~(_a.528) + 759: ~(_a.537) + 760: ~(_a.546) + 761: ~(_a.555) + 762: ~(_a.564) + 763: ~(_a.573) + 764: ~(_a.582) + 765: ~(_a.591) + 766: ~(_a.600) + 767: ~(_a.609) + 768: ~(_a.618) + 769: ~(_a.627) + 770: ~(_a.636) + 771: ~(_a.645) + 772: ~(_a.654) + 773: ~(_a.663) + 774: ~(_a.672) + 775: ~(_a.681) + 776: ~(_a.690) + 777: ~(_a.699) + 778: ~(_a.708) + 779: ~(_a.717) + 780: ~(_a.726) + 781: ~(_a.735) + 782: ~(_a.744) + 783: ~(_a.753) + 784: ~(_a.762) + 785: ~(_a.771) + 786: ~(_a.780) + 787: ~(_a.789) + 788: ~(_a.798) + 789: ~(_a.807) + 790: ~(_a.816) + 791: ~(_a.825) + 792: ~(_a.834) + 793: ~(_a.843) + 794: ~(_a.852) + 795: ~(_a.861) + 796: ~(_a.870) + 797: ~(_a.879) + 798: ~(_a.888) + 799: ~(_a.897) + 800: ~(_a.7) + 801: ~(_a.16) + 802: ~(_a.25) + 803: ~(_a.34) + 804: ~(_a.43) + 805: ~(_a.52) + 806: ~(_a.61) + 807: ~(_a.70) + 808: ~(_a.79) + 809: ~(_a.88) + 810: ~(_a.97) + 811: ~(_a.106) + 812: ~(_a.115) + 813: ~(_a.124) + 814: ~(_a.133) + 815: ~(_a.142) + 816: ~(_a.151) + 817: ~(_a.160) + 818: ~(_a.169) + 819: ~(_a.178) + 820: ~(_a.187) + 821: ~(_a.196) + 822: ~(_a.205) + 823: ~(_a.214) + 824: ~(_a.223) + 825: ~(_a.232) + 826: ~(_a.241) + 827: ~(_a.250) + 828: ~(_a.259) + 829: ~(_a.268) + 830: ~(_a.277) + 831: ~(_a.286) + 832: ~(_a.295) + 833: ~(_a.304) + 834: ~(_a.313) + 835: ~(_a.322) + 836: ~(_a.331) + 837: ~(_a.340) + 838: ~(_a.349) + 839: ~(_a.358) + 840: ~(_a.367) + 841: ~(_a.376) + 842: ~(_a.385) + 843: ~(_a.394) + 844: ~(_a.403) + 845: ~(_a.412) + 846: ~(_a.421) + 847: ~(_a.430) + 848: ~(_a.439) + 849: ~(_a.448) + 850: ~(_a.457) + 851: ~(_a.466) + 852: ~(_a.475) + 853: ~(_a.484) + 854: ~(_a.493) + 855: ~(_a.502) + 856: ~(_a.511) + 857: ~(_a.520) + 858: ~(_a.529) + 859: ~(_a.538) + 860: ~(_a.547) + 861: ~(_a.556) + 862: ~(_a.565) + 863: ~(_a.574) + 864: ~(_a.583) + 865: ~(_a.592) + 866: ~(_a.601) + 867: ~(_a.610) + 868: ~(_a.619) + 869: ~(_a.628) + 870: ~(_a.637) + 871: ~(_a.646) + 872: ~(_a.655) + 873: ~(_a.664) + 874: ~(_a.673) + 875: ~(_a.682) + 876: ~(_a.691) + 877: ~(_a.700) + 878: ~(_a.709) + 879: ~(_a.718) + 880: ~(_a.727) + 881: ~(_a.736) + 882: ~(_a.745) + 883: ~(_a.754) + 884: ~(_a.763) + 885: ~(_a.772) + 886: ~(_a.781) + 887: ~(_a.790) + 888: ~(_a.799) + 889: ~(_a.808) + 890: ~(_a.817) + 891: ~(_a.826) + 892: ~(_a.835) + 893: ~(_a.844) + 894: ~(_a.853) + 895: ~(_a.862) + 896: ~(_a.871) + 897: ~(_a.880) + 898: ~(_a.889) + 899: ~(_a.898) } } -- out/eval -- (struct){ _a: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } _b: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } _c: (#list){ 0: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 1: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 2: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 3: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 4: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 5: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 6: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 7: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 8: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } 9: (#list){ 0: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 1: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 2: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 3: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 4: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 5: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 6: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 7: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 8: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } 9: (#list){ 0: (struct){ name: (int){ 1 } } 1: (struct){ name: (int){ 3 } } 2: (struct){ name: (int){ 4 } } 3: (struct){ name: (int){ 5 } } 4: (struct){ name: (int){ 6 } } 5: (struct){ name: (int){ 7 } } 6: (struct){ name: (int){ 8 } } 7: (struct){ name: (int){ 9 } } 8: (struct){ name: (int){ 0 } } } } } out: (#list){ 0: (struct){ name: (int){ 0 } } 1: (struct){ name: (int){ 0 } } 2: (struct){ name: (int){ 0 } } 3: (struct){ name: (int){ 0 } } 4: (struct){ name: (int){ 0 } } 5: (struct){ name: (int){ 0 } } 6: (struct){ name: (int){ 0 } } 7: (struct){ name: (int){ 0 } } 8: (struct){ name: (int){ 0 } } 9: (struct){ name: (int){ 0 } } 10: (struct){ name: (int){ 0 } } 11: (struct){ name: (int){ 0 } } 12: (struct){ name: (int){ 0 } } 13: (struct){ name: (int){ 0 } } 14: (struct){ name: (int){ 0 } } 15: (struct){ name: (int){ 0 } } 16: (struct){ name: (int){ 0 } } 17: (struct){ name: (int){ 0 } } 18: (struct){ name: (int){ 0 } } 19: (struct){ name: (int){ 0 } } 20: (struct){ name: (int){ 0 } } 21: (struct){ name: (int){ 0 } } 22: (struct){ name: (int){ 0 } } 23: (struct){ name: (int){ 0 } } 24: (struct){ name: (int){ 0 } } 25: (struct){ name: (int){ 0 } } 26: (struct){ name: (int){ 0 } } 27: (struct){ name: (int){ 0 } } 28: (struct){ name: (int){ 0 } } 29: (struct){ name: (int){ 0 } } 30: (struct){ name: (int){ 0 } } 31: (struct){ name: (int){ 0 } } 32: (struct){ name: (int){ 0 } } 33: (struct){ name: (int){ 0 } } 34: (struct){ name: (int){ 0 } } 35: (struct){ name: (int){ 0 } } 36: (struct){ name: (int){ 0 } } 37: (struct){ name: (int){ 0 } } 38: (struct){ name: (int){ 0 } } 39: (struct){ name: (int){ 0 } } 40: (struct){ name: (int){ 0 } } 41: (struct){ name: (int){ 0 } } 42: (struct){ name: (int){ 0 } } 43: (struct){ name: (int){ 0 } } 44: (struct){ name: (int){ 0 } } 45: (struct){ name: (int){ 0 } } 46: (struct){ name: (int){ 0 } } 47: (struct){ name: (int){ 0 } } 48: (struct){ name: (int){ 0 } } 49: (struct){ name: (int){ 0 } } 50: (struct){ name: (int){ 0 } } 51: (struct){ name: (int){ 0 } } 52: (struct){ name: (int){ 0 } } 53: (struct){ name: (int){ 0 } } 54: (struct){ name: (int){ 0 } } 55: (struct){ name: (int){ 0 } } 56: (struct){ name: (int){ 0 } } 57: (struct){ name: (int){ 0 } } 58: (struct){ name: (int){ 0 } } 59: (struct){ name: (int){ 0 } } 60: (struct){ name: (int){ 0 } } 61: (struct){ name: (int){ 0 } } 62: (struct){ name: (int){ 0 } } 63: (struct){ name: (int){ 0 } } 64: (struct){ name: (int){ 0 } } 65: (struct){ name: (int){ 0 } } 66: (struct){ name: (int){ 0 } } 67: (struct){ name: (int){ 0 } } 68: (struct){ name: (int){ 0 } } 69: (struct){ name: (int){ 0 } } 70: (struct){ name: (int){ 0 } } 71: (struct){ name: (int){ 0 } } 72: (struct){ name: (int){ 0 } } 73: (struct){ name: (int){ 0 } } 74: (struct){ name: (int){ 0 } } 75: (struct){ name: (int){ 0 } } 76: (struct){ name: (int){ 0 } } 77: (struct){ name: (int){ 0 } } 78: (struct){ name: (int){ 0 } } 79: (struct){ name: (int){ 0 } } 80: (struct){ name: (int){ 0 } } 81: (struct){ name: (int){ 0 } } 82: (struct){ name: (int){ 0 } } 83: (struct){ name: (int){ 0 } } 84: (struct){ name: (int){ 0 } } 85: (struct){ name: (int){ 0 } } 86: (struct){ name: (int){ 0 } } 87: (struct){ name: (int){ 0 } } 88: (struct){ name: (int){ 0 } } 89: (struct){ name: (int){ 0 } } 90: (struct){ name: (int){ 0 } } 91: (struct){ name: (int){ 0 } } 92: (struct){ name: (int){ 0 } } 93: (struct){ name: (int){ 0 } } 94: (struct){ name: (int){ 0 } } 95: (struct){ name: (int){ 0 } } 96: (struct){ name: (int){ 0 } } 97: (struct){ name: (int){ 0 } } 98: (struct){ name: (int){ 0 } } 99: (struct){ name: (int){ 0 } } 100: (struct){ name: (int){ 1 } } 101: (struct){ name: (int){ 1 } } 102: (struct){ name: (int){ 1 } } 103: (struct){ name: (int){ 1 } } 104: (struct){ name: (int){ 1 } } 105: (struct){ name: (int){ 1 } } 106: (struct){ name: (int){ 1 } } 107: (struct){ name: (int){ 1 } } 108: (struct){ name: (int){ 1 } } 109: (struct){ name: (int){ 1 } } 110: (struct){ name: (int){ 1 } } 111: (struct){ name: (int){ 1 } } 112: (struct){ name: (int){ 1 } } 113: (struct){ name: (int){ 1 } } 114: (struct){ name: (int){ 1 } } 115: (struct){ name: (int){ 1 } } 116: (struct){ name: (int){ 1 } } 117: (struct){ name: (int){ 1 } } 118: (struct){ name: (int){ 1 } } 119: (struct){ name: (int){ 1 } } 120: (struct){ name: (int){ 1 } } 121: (struct){ name: (int){ 1 } } 122: (struct){ name: (int){ 1 } } 123: (struct){ name: (int){ 1 } } 124: (struct){ name: (int){ 1 } } 125: (struct){ name: (int){ 1 } } 126: (struct){ name: (int){ 1 } } 127: (struct){ name: (int){ 1 } } 128: (struct){ name: (int){ 1 } } 129: (struct){ name: (int){ 1 } } 130: (struct){ name: (int){ 1 } } 131: (struct){ name: (int){ 1 } } 132: (struct){ name: (int){ 1 } } 133: (struct){ name: (int){ 1 } } 134: (struct){ name: (int){ 1 } } 135: (struct){ name: (int){ 1 } } 136: (struct){ name: (int){ 1 } } 137: (struct){ name: (int){ 1 } } 138: (struct){ name: (int){ 1 } } 139: (struct){ name: (int){ 1 } } 140: (struct){ name: (int){ 1 } } 141: (struct){ name: (int){ 1 } } 142: (struct){ name: (int){ 1 } } 143: (struct){ name: (int){ 1 } } 144: (struct){ name: (int){ 1 } } 145: (struct){ name: (int){ 1 } } 146: (struct){ name: (int){ 1 } } 147: (struct){ name: (int){ 1 } } 148: (struct){ name: (int){ 1 } } 149: (struct){ name: (int){ 1 } } 150: (struct){ name: (int){ 1 } } 151: (struct){ name: (int){ 1 } } 152: (struct){ name: (int){ 1 } } 153: (struct){ name: (int){ 1 } } 154: (struct){ name: (int){ 1 } } 155: (struct){ name: (int){ 1 } } 156: (struct){ name: (int){ 1 } } 157: (struct){ name: (int){ 1 } } 158: (struct){ name: (int){ 1 } } 159: (struct){ name: (int){ 1 } } 160: (struct){ name: (int){ 1 } } 161: (struct){ name: (int){ 1 } } 162: (struct){ name: (int){ 1 } } 163: (struct){ name: (int){ 1 } } 164: (struct){ name: (int){ 1 } } 165: (struct){ name: (int){ 1 } } 166: (struct){ name: (int){ 1 } } 167: (struct){ name: (int){ 1 } } 168: (struct){ name: (int){ 1 } } 169: (struct){ name: (int){ 1 } } 170: (struct){ name: (int){ 1 } } 171: (struct){ name: (int){ 1 } } 172: (struct){ name: (int){ 1 } } 173: (struct){ name: (int){ 1 } } 174: (struct){ name: (int){ 1 } } 175: (struct){ name: (int){ 1 } } 176: (struct){ name: (int){ 1 } } 177: (struct){ name: (int){ 1 } } 178: (struct){ name: (int){ 1 } } 179: (struct){ name: (int){ 1 } } 180: (struct){ name: (int){ 1 } } 181: (struct){ name: (int){ 1 } } 182: (struct){ name: (int){ 1 } } 183: (struct){ name: (int){ 1 } } 184: (struct){ name: (int){ 1 } } 185: (struct){ name: (int){ 1 } } 186: (struct){ name: (int){ 1 } } 187: (struct){ name: (int){ 1 } } 188: (struct){ name: (int){ 1 } } 189: (struct){ name: (int){ 1 } } 190: (struct){ name: (int){ 1 } } 191: (struct){ name: (int){ 1 } } 192: (struct){ name: (int){ 1 } } 193: (struct){ name: (int){ 1 } } 194: (struct){ name: (int){ 1 } } 195: (struct){ name: (int){ 1 } } 196: (struct){ name: (int){ 1 } } 197: (struct){ name: (int){ 1 } } 198: (struct){ name: (int){ 1 } } 199: (struct){ name: (int){ 1 } } 200: (struct){ name: (int){ 3 } } 201: (struct){ name: (int){ 3 } } 202: (struct){ name: (int){ 3 } } 203: (struct){ name: (int){ 3 } } 204: (struct){ name: (int){ 3 } } 205: (struct){ name: (int){ 3 } } 206: (struct){ name: (int){ 3 } } 207: (struct){ name: (int){ 3 } } 208: (struct){ name: (int){ 3 } } 209: (struct){ name: (int){ 3 } } 210: (struct){ name: (int){ 3 } } 211: (struct){ name: (int){ 3 } } 212: (struct){ name: (int){ 3 } } 213: (struct){ name: (int){ 3 } } 214: (struct){ name: (int){ 3 } } 215: (struct){ name: (int){ 3 } } 216: (struct){ name: (int){ 3 } } 217: (struct){ name: (int){ 3 } } 218: (struct){ name: (int){ 3 } } 219: (struct){ name: (int){ 3 } } 220: (struct){ name: (int){ 3 } } 221: (struct){ name: (int){ 3 } } 222: (struct){ name: (int){ 3 } } 223: (struct){ name: (int){ 3 } } 224: (struct){ name: (int){ 3 } } 225: (struct){ name: (int){ 3 } } 226: (struct){ name: (int){ 3 } } 227: (struct){ name: (int){ 3 } } 228: (struct){ name: (int){ 3 } } 229: (struct){ name: (int){ 3 } } 230: (struct){ name: (int){ 3 } } 231: (struct){ name: (int){ 3 } } 232: (struct){ name: (int){ 3 } } 233: (struct){ name: (int){ 3 } } 234: (struct){ name: (int){ 3 } } 235: (struct){ name: (int){ 3 } } 236: (struct){ name: (int){ 3 } } 237: (struct){ name: (int){ 3 } } 238: (struct){ name: (int){ 3 } } 239: (struct){ name: (int){ 3 } } 240: (struct){ name: (int){ 3 } } 241: (struct){ name: (int){ 3 } } 242: (struct){ name: (int){ 3 } } 243: (struct){ name: (int){ 3 } } 244: (struct){ name: (int){ 3 } } 245: (struct){ name: (int){ 3 } } 246: (struct){ name: (int){ 3 } } 247: (struct){ name: (int){ 3 } } 248: (struct){ name: (int){ 3 } } 249: (struct){ name: (int){ 3 } } 250: (struct){ name: (int){ 3 } } 251: (struct){ name: (int){ 3 } } 252: (struct){ name: (int){ 3 } } 253: (struct){ name: (int){ 3 } } 254: (struct){ name: (int){ 3 } } 255: (struct){ name: (int){ 3 } } 256: (struct){ name: (int){ 3 } } 257: (struct){ name: (int){ 3 } } 258: (struct){ name: (int){ 3 } } 259: (struct){ name: (int){ 3 } } 260: (struct){ name: (int){ 3 } } 261: (struct){ name: (int){ 3 } } 262: (struct){ name: (int){ 3 } } 263: (struct){ name: (int){ 3 } } 264: (struct){ name: (int){ 3 } } 265: (struct){ name: (int){ 3 } } 266: (struct){ name: (int){ 3 } } 267: (struct){ name: (int){ 3 } } 268: (struct){ name: (int){ 3 } } 269: (struct){ name: (int){ 3 } } 270: (struct){ name: (int){ 3 } } 271: (struct){ name: (int){ 3 } } 272: (struct){ name: (int){ 3 } } 273: (struct){ name: (int){ 3 } } 274: (struct){ name: (int){ 3 } } 275: (struct){ name: (int){ 3 } } 276: (struct){ name: (int){ 3 } } 277: (struct){ name: (int){ 3 } } 278: (struct){ name: (int){ 3 } } 279: (struct){ name: (int){ 3 } } 280: (struct){ name: (int){ 3 } } 281: (struct){ name: (int){ 3 } } 282: (struct){ name: (int){ 3 } } 283: (struct){ name: (int){ 3 } } 284: (struct){ name: (int){ 3 } } 285: (struct){ name: (int){ 3 } } 286: (struct){ name: (int){ 3 } } 287: (struct){ name: (int){ 3 } } 288: (struct){ name: (int){ 3 } } 289: (struct){ name: (int){ 3 } } 290: (struct){ name: (int){ 3 } } 291: (struct){ name: (int){ 3 } } 292: (struct){ name: (int){ 3 } } 293: (struct){ name: (int){ 3 } } 294: (struct){ name: (int){ 3 } } 295: (struct){ name: (int){ 3 } } 296: (struct){ name: (int){ 3 } } 297: (struct){ name: (int){ 3 } } 298: (struct){ name: (int){ 3 } } 299: (struct){ name: (int){ 3 } } 300: (struct){ name: (int){ 4 } } 301: (struct){ name: (int){ 4 } } 302: (struct){ name: (int){ 4 } } 303: (struct){ name: (int){ 4 } } 304: (struct){ name: (int){ 4 } } 305: (struct){ name: (int){ 4 } } 306: (struct){ name: (int){ 4 } } 307: (struct){ name: (int){ 4 } } 308: (struct){ name: (int){ 4 } } 309: (struct){ name: (int){ 4 } } 310: (struct){ name: (int){ 4 } } 311: (struct){ name: (int){ 4 } } 312: (struct){ name: (int){ 4 } } 313: (struct){ name: (int){ 4 } } 314: (struct){ name: (int){ 4 } } 315: (struct){ name: (int){ 4 } } 316: (struct){ name: (int){ 4 } } 317: (struct){ name: (int){ 4 } } 318: (struct){ name: (int){ 4 } } 319: (struct){ name: (int){ 4 } } 320: (struct){ name: (int){ 4 } } 321: (struct){ name: (int){ 4 } } 322: (struct){ name: (int){ 4 } } 323: (struct){ name: (int){ 4 } } 324: (struct){ name: (int){ 4 } } 325: (struct){ name: (int){ 4 } } 326: (struct){ name: (int){ 4 } } 327: (struct){ name: (int){ 4 } } 328: (struct){ name: (int){ 4 } } 329: (struct){ name: (int){ 4 } } 330: (struct){ name: (int){ 4 } } 331: (struct){ name: (int){ 4 } } 332: (struct){ name: (int){ 4 } } 333: (struct){ name: (int){ 4 } } 334: (struct){ name: (int){ 4 } } 335: (struct){ name: (int){ 4 } } 336: (struct){ name: (int){ 4 } } 337: (struct){ name: (int){ 4 } } 338: (struct){ name: (int){ 4 } } 339: (struct){ name: (int){ 4 } } 340: (struct){ name: (int){ 4 } } 341: (struct){ name: (int){ 4 } } 342: (struct){ name: (int){ 4 } } 343: (struct){ name: (int){ 4 } } 344: (struct){ name: (int){ 4 } } 345: (struct){ name: (int){ 4 } } 346: (struct){ name: (int){ 4 } } 347: (struct){ name: (int){ 4 } } 348: (struct){ name: (int){ 4 } } 349: (struct){ name: (int){ 4 } } 350: (struct){ name: (int){ 4 } } 351: (struct){ name: (int){ 4 } } 352: (struct){ name: (int){ 4 } } 353: (struct){ name: (int){ 4 } } 354: (struct){ name: (int){ 4 } } 355: (struct){ name: (int){ 4 } } 356: (struct){ name: (int){ 4 } } 357: (struct){ name: (int){ 4 } } 358: (struct){ name: (int){ 4 } } 359: (struct){ name: (int){ 4 } } 360: (struct){ name: (int){ 4 } } 361: (struct){ name: (int){ 4 } } 362: (struct){ name: (int){ 4 } } 363: (struct){ name: (int){ 4 } } 364: (struct){ name: (int){ 4 } } 365: (struct){ name: (int){ 4 } } 366: (struct){ name: (int){ 4 } } 367: (struct){ name: (int){ 4 } } 368: (struct){ name: (int){ 4 } } 369: (struct){ name: (int){ 4 } } 370: (struct){ name: (int){ 4 } } 371: (struct){ name: (int){ 4 } } 372: (struct){ name: (int){ 4 } } 373: (struct){ name: (int){ 4 } } 374: (struct){ name: (int){ 4 } } 375: (struct){ name: (int){ 4 } } 376: (struct){ name: (int){ 4 } } 377: (struct){ name: (int){ 4 } } 378: (struct){ name: (int){ 4 } } 379: (struct){ name: (int){ 4 } } 380: (struct){ name: (int){ 4 } } 381: (struct){ name: (int){ 4 } } 382: (struct){ name: (int){ 4 } } 383: (struct){ name: (int){ 4 } } 384: (struct){ name: (int){ 4 } } 385: (struct){ name: (int){ 4 } } 386: (struct){ name: (int){ 4 } } 387: (struct){ name: (int){ 4 } } 388: (struct){ name: (int){ 4 } } 389: (struct){ name: (int){ 4 } } 390: (struct){ name: (int){ 4 } } 391: (struct){ name: (int){ 4 } } 392: (struct){ name: (int){ 4 } } 393: (struct){ name: (int){ 4 } } 394: (struct){ name: (int){ 4 } } 395: (struct){ name: (int){ 4 } } 396: (struct){ name: (int){ 4 } } 397: (struct){ name: (int){ 4 } } 398: (struct){ name: (int){ 4 } } 399: (struct){ name: (int){ 4 } } 400: (struct){ name: (int){ 5 } } 401: (struct){ name: (int){ 5 } } 402: (struct){ name: (int){ 5 } } 403: (struct){ name: (int){ 5 } } 404: (struct){ name: (int){ 5 } } 405: (struct){ name: (int){ 5 } } 406: (struct){ name: (int){ 5 } } 407: (struct){ name: (int){ 5 } } 408: (struct){ name: (int){ 5 } } 409: (struct){ name: (int){ 5 } } 410: (struct){ name: (int){ 5 } } 411: (struct){ name: (int){ 5 } } 412: (struct){ name: (int){ 5 } } 413: (struct){ name: (int){ 5 } } 414: (struct){ name: (int){ 5 } } 415: (struct){ name: (int){ 5 } } 416: (struct){ name: (int){ 5 } } 417: (struct){ name: (int){ 5 } } 418: (struct){ name: (int){ 5 } } 419: (struct){ name: (int){ 5 } } 420: (struct){ name: (int){ 5 } } 421: (struct){ name: (int){ 5 } } 422: (struct){ name: (int){ 5 } } 423: (struct){ name: (int){ 5 } } 424: (struct){ name: (int){ 5 } } 425: (struct){ name: (int){ 5 } } 426: (struct){ name: (int){ 5 } } 427: (struct){ name: (int){ 5 } } 428: (struct){ name: (int){ 5 } } 429: (struct){ name: (int){ 5 } } 430: (struct){ name: (int){ 5 } } 431: (struct){ name: (int){ 5 } } 432: (struct){ name: (int){ 5 } } 433: (struct){ name: (int){ 5 } } 434: (struct){ name: (int){ 5 } } 435: (struct){ name: (int){ 5 } } 436: (struct){ name: (int){ 5 } } 437: (struct){ name: (int){ 5 } } 438: (struct){ name: (int){ 5 } } 439: (struct){ name: (int){ 5 } } 440: (struct){ name: (int){ 5 } } 441: (struct){ name: (int){ 5 } } 442: (struct){ name: (int){ 5 } } 443: (struct){ name: (int){ 5 } } 444: (struct){ name: (int){ 5 } } 445: (struct){ name: (int){ 5 } } 446: (struct){ name: (int){ 5 } } 447: (struct){ name: (int){ 5 } } 448: (struct){ name: (int){ 5 } } 449: (struct){ name: (int){ 5 } } 450: (struct){ name: (int){ 5 } } 451: (struct){ name: (int){ 5 } } 452: (struct){ name: (int){ 5 } } 453: (struct){ name: (int){ 5 } } 454: (struct){ name: (int){ 5 } } 455: (struct){ name: (int){ 5 } } 456: (struct){ name: (int){ 5 } } 457: (struct){ name: (int){ 5 } } 458: (struct){ name: (int){ 5 } } 459: (struct){ name: (int){ 5 } } 460: (struct){ name: (int){ 5 } } 461: (struct){ name: (int){ 5 } } 462: (struct){ name: (int){ 5 } } 463: (struct){ name: (int){ 5 } } 464: (struct){ name: (int){ 5 } } 465: (struct){ name: (int){ 5 } } 466: (struct){ name: (int){ 5 } } 467: (struct){ name: (int){ 5 } } 468: (struct){ name: (int){ 5 } } 469: (struct){ name: (int){ 5 } } 470: (struct){ name: (int){ 5 } } 471: (struct){ name: (int){ 5 } } 472: (struct){ name: (int){ 5 } } 473: (struct){ name: (int){ 5 } } 474: (struct){ name: (int){ 5 } } 475: (struct){ name: (int){ 5 } } 476: (struct){ name: (int){ 5 } } 477: (struct){ name: (int){ 5 } } 478: (struct){ name: (int){ 5 } } 479: (struct){ name: (int){ 5 } } 480: (struct){ name: (int){ 5 } } 481: (struct){ name: (int){ 5 } } 482: (struct){ name: (int){ 5 } } 483: (struct){ name: (int){ 5 } } 484: (struct){ name: (int){ 5 } } 485: (struct){ name: (int){ 5 } } 486: (struct){ name: (int){ 5 } } 487: (struct){ name: (int){ 5 } } 488: (struct){ name: (int){ 5 } } 489: (struct){ name: (int){ 5 } } 490: (struct){ name: (int){ 5 } } 491: (struct){ name: (int){ 5 } } 492: (struct){ name: (int){ 5 } } 493: (struct){ name: (int){ 5 } } 494: (struct){ name: (int){ 5 } } 495: (struct){ name: (int){ 5 } } 496: (struct){ name: (int){ 5 } } 497: (struct){ name: (int){ 5 } } 498: (struct){ name: (int){ 5 } } 499: (struct){ name: (int){ 5 } } 500: (struct){ name: (int){ 6 } } 501: (struct){ name: (int){ 6 } } 502: (struct){ name: (int){ 6 } } 503: (struct){ name: (int){ 6 } } 504: (struct){ name: (int){ 6 } } 505: (struct){ name: (int){ 6 } } 506: (struct){ name: (int){ 6 } } 507: (struct){ name: (int){ 6 } } 508: (struct){ name: (int){ 6 } } 509: (struct){ name: (int){ 6 } } 510: (struct){ name: (int){ 6 } } 511: (struct){ name: (int){ 6 } } 512: (struct){ name: (int){ 6 } } 513: (struct){ name: (int){ 6 } } 514: (struct){ name: (int){ 6 } } 515: (struct){ name: (int){ 6 } } 516: (struct){ name: (int){ 6 } } 517: (struct){ name: (int){ 6 } } 518: (struct){ name: (int){ 6 } } 519: (struct){ name: (int){ 6 } } 520: (struct){ name: (int){ 6 } } 521: (struct){ name: (int){ 6 } } 522: (struct){ name: (int){ 6 } } 523: (struct){ name: (int){ 6 } } 524: (struct){ name: (int){ 6 } } 525: (struct){ name: (int){ 6 } } 526: (struct){ name: (int){ 6 } } 527: (struct){ name: (int){ 6 } } 528: (struct){ name: (int){ 6 } } 529: (struct){ name: (int){ 6 } } 530: (struct){ name: (int){ 6 } } 531: (struct){ name: (int){ 6 } } 532: (struct){ name: (int){ 6 } } 533: (struct){ name: (int){ 6 } } 534: (struct){ name: (int){ 6 } } 535: (struct){ name: (int){ 6 } } 536: (struct){ name: (int){ 6 } } 537: (struct){ name: (int){ 6 } } 538: (struct){ name: (int){ 6 } } 539: (struct){ name: (int){ 6 } } 540: (struct){ name: (int){ 6 } } 541: (struct){ name: (int){ 6 } } 542: (struct){ name: (int){ 6 } } 543: (struct){ name: (int){ 6 } } 544: (struct){ name: (int){ 6 } } 545: (struct){ name: (int){ 6 } } 546: (struct){ name: (int){ 6 } } 547: (struct){ name: (int){ 6 } } 548: (struct){ name: (int){ 6 } } 549: (struct){ name: (int){ 6 } } 550: (struct){ name: (int){ 6 } } 551: (struct){ name: (int){ 6 } } 552: (struct){ name: (int){ 6 } } 553: (struct){ name: (int){ 6 } } 554: (struct){ name: (int){ 6 } } 555: (struct){ name: (int){ 6 } } 556: (struct){ name: (int){ 6 } } 557: (struct){ name: (int){ 6 } } 558: (struct){ name: (int){ 6 } } 559: (struct){ name: (int){ 6 } } 560: (struct){ name: (int){ 6 } } 561: (struct){ name: (int){ 6 } } 562: (struct){ name: (int){ 6 } } 563: (struct){ name: (int){ 6 } } 564: (struct){ name: (int){ 6 } } 565: (struct){ name: (int){ 6 } } 566: (struct){ name: (int){ 6 } } 567: (struct){ name: (int){ 6 } } 568: (struct){ name: (int){ 6 } } 569: (struct){ name: (int){ 6 } } 570: (struct){ name: (int){ 6 } } 571: (struct){ name: (int){ 6 } } 572: (struct){ name: (int){ 6 } } 573: (struct){ name: (int){ 6 } } 574: (struct){ name: (int){ 6 } } 575: (struct){ name: (int){ 6 } } 576: (struct){ name: (int){ 6 } } 577: (struct){ name: (int){ 6 } } 578: (struct){ name: (int){ 6 } } 579: (struct){ name: (int){ 6 } } 580: (struct){ name: (int){ 6 } } 581: (struct){ name: (int){ 6 } } 582: (struct){ name: (int){ 6 } } 583: (struct){ name: (int){ 6 } } 584: (struct){ name: (int){ 6 } } 585: (struct){ name: (int){ 6 } } 586: (struct){ name: (int){ 6 } } 587: (struct){ name: (int){ 6 } } 588: (struct){ name: (int){ 6 } } 589: (struct){ name: (int){ 6 } } 590: (struct){ name: (int){ 6 } } 591: (struct){ name: (int){ 6 } } 592: (struct){ name: (int){ 6 } } 593: (struct){ name: (int){ 6 } } 594: (struct){ name: (int){ 6 } } 595: (struct){ name: (int){ 6 } } 596: (struct){ name: (int){ 6 } } 597: (struct){ name: (int){ 6 } } 598: (struct){ name: (int){ 6 } } 599: (struct){ name: (int){ 6 } } 600: (struct){ name: (int){ 7 } } 601: (struct){ name: (int){ 7 } } 602: (struct){ name: (int){ 7 } } 603: (struct){ name: (int){ 7 } } 604: (struct){ name: (int){ 7 } } 605: (struct){ name: (int){ 7 } } 606: (struct){ name: (int){ 7 } } 607: (struct){ name: (int){ 7 } } 608: (struct){ name: (int){ 7 } } 609: (struct){ name: (int){ 7 } } 610: (struct){ name: (int){ 7 } } 611: (struct){ name: (int){ 7 } } 612: (struct){ name: (int){ 7 } } 613: (struct){ name: (int){ 7 } } 614: (struct){ name: (int){ 7 } } 615: (struct){ name: (int){ 7 } } 616: (struct){ name: (int){ 7 } } 617: (struct){ name: (int){ 7 } } 618: (struct){ name: (int){ 7 } } 619: (struct){ name: (int){ 7 } } 620: (struct){ name: (int){ 7 } } 621: (struct){ name: (int){ 7 } } 622: (struct){ name: (int){ 7 } } 623: (struct){ name: (int){ 7 } } 624: (struct){ name: (int){ 7 } } 625: (struct){ name: (int){ 7 } } 626: (struct){ name: (int){ 7 } } 627: (struct){ name: (int){ 7 } } 628: (struct){ name: (int){ 7 } } 629: (struct){ name: (int){ 7 } } 630: (struct){ name: (int){ 7 } } 631: (struct){ name: (int){ 7 } } 632: (struct){ name: (int){ 7 } } 633: (struct){ name: (int){ 7 } } 634: (struct){ name: (int){ 7 } } 635: (struct){ name: (int){ 7 } } 636: (struct){ name: (int){ 7 } } 637: (struct){ name: (int){ 7 } } 638: (struct){ name: (int){ 7 } } 639: (struct){ name: (int){ 7 } } 640: (struct){ name: (int){ 7 } } 641: (struct){ name: (int){ 7 } } 642: (struct){ name: (int){ 7 } } 643: (struct){ name: (int){ 7 } } 644: (struct){ name: (int){ 7 } } 645: (struct){ name: (int){ 7 } } 646: (struct){ name: (int){ 7 } } 647: (struct){ name: (int){ 7 } } 648: (struct){ name: (int){ 7 } } 649: (struct){ name: (int){ 7 } } 650: (struct){ name: (int){ 7 } } 651: (struct){ name: (int){ 7 } } 652: (struct){ name: (int){ 7 } } 653: (struct){ name: (int){ 7 } } 654: (struct){ name: (int){ 7 } } 655: (struct){ name: (int){ 7 } } 656: (struct){ name: (int){ 7 } } 657: (struct){ name: (int){ 7 } } 658: (struct){ name: (int){ 7 } } 659: (struct){ name: (int){ 7 } } 660: (struct){ name: (int){ 7 } } 661: (struct){ name: (int){ 7 } } 662: (struct){ name: (int){ 7 } } 663: (struct){ name: (int){ 7 } } 664: (struct){ name: (int){ 7 } } 665: (struct){ name: (int){ 7 } } 666: (struct){ name: (int){ 7 } } 667: (struct){ name: (int){ 7 } } 668: (struct){ name: (int){ 7 } } 669: (struct){ name: (int){ 7 } } 670: (struct){ name: (int){ 7 } } 671: (struct){ name: (int){ 7 } } 672: (struct){ name: (int){ 7 } } 673: (struct){ name: (int){ 7 } } 674: (struct){ name: (int){ 7 } } 675: (struct){ name: (int){ 7 } } 676: (struct){ name: (int){ 7 } } 677: (struct){ name: (int){ 7 } } 678: (struct){ name: (int){ 7 } } 679: (struct){ name: (int){ 7 } } 680: (struct){ name: (int){ 7 } } 681: (struct){ name: (int){ 7 } } 682: (struct){ name: (int){ 7 } } 683: (struct){ name: (int){ 7 } } 684: (struct){ name: (int){ 7 } } 685: (struct){ name: (int){ 7 } } 686: (struct){ name: (int){ 7 } } 687: (struct){ name: (int){ 7 } } 688: (struct){ name: (int){ 7 } } 689: (struct){ name: (int){ 7 } } 690: (struct){ name: (int){ 7 } } 691: (struct){ name: (int){ 7 } } 692: (struct){ name: (int){ 7 } } 693: (struct){ name: (int){ 7 } } 694: (struct){ name: (int){ 7 } } 695: (struct){ name: (int){ 7 } } 696: (struct){ name: (int){ 7 } } 697: (struct){ name: (int){ 7 } } 698: (struct){ name: (int){ 7 } } 699: (struct){ name: (int){ 7 } } 700: (struct){ name: (int){ 8 } } 701: (struct){ name: (int){ 8 } } 702: (struct){ name: (int){ 8 } } 703: (struct){ name: (int){ 8 } } 704: (struct){ name: (int){ 8 } } 705: (struct){ name: (int){ 8 } } 706: (struct){ name: (int){ 8 } } 707: (struct){ name: (int){ 8 } } 708: (struct){ name: (int){ 8 } } 709: (struct){ name: (int){ 8 } } 710: (struct){ name: (int){ 8 } } 711: (struct){ name: (int){ 8 } } 712: (struct){ name: (int){ 8 } } 713: (struct){ name: (int){ 8 } } 714: (struct){ name: (int){ 8 } } 715: (struct){ name: (int){ 8 } } 716: (struct){ name: (int){ 8 } } 717: (struct){ name: (int){ 8 } } 718: (struct){ name: (int){ 8 } } 719: (struct){ name: (int){ 8 } } 720: (struct){ name: (int){ 8 } } 721: (struct){ name: (int){ 8 } } 722: (struct){ name: (int){ 8 } } 723: (struct){ name: (int){ 8 } } 724: (struct){ name: (int){ 8 } } 725: (struct){ name: (int){ 8 } } 726: (struct){ name: (int){ 8 } } 727: (struct){ name: (int){ 8 } } 728: (struct){ name: (int){ 8 } } 729: (struct){ name: (int){ 8 } } 730: (struct){ name: (int){ 8 } } 731: (struct){ name: (int){ 8 } } 732: (struct){ name: (int){ 8 } } 733: (struct){ name: (int){ 8 } } 734: (struct){ name: (int){ 8 } } 735: (struct){ name: (int){ 8 } } 736: (struct){ name: (int){ 8 } } 737: (struct){ name: (int){ 8 } } 738: (struct){ name: (int){ 8 } } 739: (struct){ name: (int){ 8 } } 740: (struct){ name: (int){ 8 } } 741: (struct){ name: (int){ 8 } } 742: (struct){ name: (int){ 8 } } 743: (struct){ name: (int){ 8 } } 744: (struct){ name: (int){ 8 } } 745: (struct){ name: (int){ 8 } } 746: (struct){ name: (int){ 8 } } 747: (struct){ name: (int){ 8 } } 748: (struct){ name: (int){ 8 } } 749: (struct){ name: (int){ 8 } } 750: (struct){ name: (int){ 8 } } 751: (struct){ name: (int){ 8 } } 752: (struct){ name: (int){ 8 } } 753: (struct){ name: (int){ 8 } } 754: (struct){ name: (int){ 8 } } 755: (struct){ name: (int){ 8 } } 756: (struct){ name: (int){ 8 } } 757: (struct){ name: (int){ 8 } } 758: (struct){ name: (int){ 8 } } 759: (struct){ name: (int){ 8 } } 760: (struct){ name: (int){ 8 } } 761: (struct){ name: (int){ 8 } } 762: (struct){ name: (int){ 8 } } 763: (struct){ name: (int){ 8 } } 764: (struct){ name: (int){ 8 } } 765: (struct){ name: (int){ 8 } } 766: (struct){ name: (int){ 8 } } 767: (struct){ name: (int){ 8 } } 768: (struct){ name: (int){ 8 } } 769: (struct){ name: (int){ 8 } } 770: (struct){ name: (int){ 8 } } 771: (struct){ name: (int){ 8 } } 772: (struct){ name: (int){ 8 } } 773: (struct){ name: (int){ 8 } } 774: (struct){ name: (int){ 8 } } 775: (struct){ name: (int){ 8 } } 776: (struct){ name: (int){ 8 } } 777: (struct){ name: (int){ 8 } } 778: (struct){ name: (int){ 8 } } 779: (struct){ name: (int){ 8 } } 780: (struct){ name: (int){ 8 } } 781: (struct){ name: (int){ 8 } } 782: (struct){ name: (int){ 8 } } 783: (struct){ name: (int){ 8 } } 784: (struct){ name: (int){ 8 } } 785: (struct){ name: (int){ 8 } } 786: (struct){ name: (int){ 8 } } 787: (struct){ name: (int){ 8 } } 788: (struct){ name: (int){ 8 } } 789: (struct){ name: (int){ 8 } } 790: (struct){ name: (int){ 8 } } 791: (struct){ name: (int){ 8 } } 792: (struct){ name: (int){ 8 } } 793: (struct){ name: (int){ 8 } } 794: (struct){ name: (int){ 8 } } 795: (struct){ name: (int){ 8 } } 796: (struct){ name: (int){ 8 } } 797: (struct){ name: (int){ 8 } } 798: (struct){ name: (int){ 8 } } 799: (struct){ name: (int){ 8 } } 800: (struct){ name: (int){ 9 } } 801: (struct){ name: (int){ 9 } } 802: (struct){ name: (int){ 9 } } 803: (struct){ name: (int){ 9 } } 804: (struct){ name: (int){ 9 } } 805: (struct){ name: (int){ 9 } } 806: (struct){ name: (int){ 9 } } 807: (struct){ name: (int){ 9 } } 808: (struct){ name: (int){ 9 } } 809: (struct){ name: (int){ 9 } } 810: (struct){ name: (int){ 9 } } 811: (struct){ name: (int){ 9 } } 812: (struct){ name: (int){ 9 } } 813: (struct){ name: (int){ 9 } } 814: (struct){ name: (int){ 9 } } 815: (struct){ name: (int){ 9 } } 816: (struct){ name: (int){ 9 } } 817: (struct){ name: (int){ 9 } } 818: (struct){ name: (int){ 9 } } 819: (struct){ name: (int){ 9 } } 820: (struct){ name: (int){ 9 } } 821: (struct){ name: (int){ 9 } } 822: (struct){ name: (int){ 9 } } 823: (struct){ name: (int){ 9 } } 824: (struct){ name: (int){ 9 } } 825: (struct){ name: (int){ 9 } } 826: (struct){ name: (int){ 9 } } 827: (struct){ name: (int){ 9 } } 828: (struct){ name: (int){ 9 } } 829: (struct){ name: (int){ 9 } } 830: (struct){ name: (int){ 9 } } 831: (struct){ name: (int){ 9 } } 832: (struct){ name: (int){ 9 } } 833: (struct){ name: (int){ 9 } } 834: (struct){ name: (int){ 9 } } 835: (struct){ name: (int){ 9 } } 836: (struct){ name: (int){ 9 } } 837: (struct){ name: (int){ 9 } } 838: (struct){ name: (int){ 9 } } 839: (struct){ name: (int){ 9 } } 840: (struct){ name: (int){ 9 } } 841: (struct){ name: (int){ 9 } } 842: (struct){ name: (int){ 9 } } 843: (struct){ name: (int){ 9 } } 844: (struct){ name: (int){ 9 } } 845: (struct){ name: (int){ 9 } } 846: (struct){ name: (int){ 9 } } 847: (struct){ name: (int){ 9 } } 848: (struct){ name: (int){ 9 } } 849: (struct){ name: (int){ 9 } } 850: (struct){ name: (int){ 9 } } 851: (struct){ name: (int){ 9 } } 852: (struct){ name: (int){ 9 } } 853: (struct){ name: (int){ 9 } } 854: (struct){ name: (int){ 9 } } 855: (struct){ name: (int){ 9 } } 856: (struct){ name: (int){ 9 } } 857: (struct){ name: (int){ 9 } } 858: (struct){ name: (int){ 9 } } 859: (struct){ name: (int){ 9 } } 860: (struct){ name: (int){ 9 } } 861: (struct){ name: (int){ 9 } } 862: (struct){ name: (int){ 9 } } 863: (struct){ name: (int){ 9 } } 864: (struct){ name: (int){ 9 } } 865: (struct){ name: (int){ 9 } } 866: (struct){ name: (int){ 9 } } 867: (struct){ name: (int){ 9 } } 868: (struct){ name: (int){ 9 } } 869: (struct){ name: (int){ 9 } } 870: (struct){ name: (int){ 9 } } 871: (struct){ name: (int){ 9 } } 872: (struct){ name: (int){ 9 } } 873: (struct){ name: (int){ 9 } } 874: (struct){ name: (int){ 9 } } 875: (struct){ name: (int){ 9 } } 876: (struct){ name: (int){ 9 } } 877: (struct){ name: (int){ 9 } } 878: (struct){ name: (int){ 9 } } 879: (struct){ name: (int){ 9 } } 880: (struct){ name: (int){ 9 } } 881: (struct){ name: (int){ 9 } } 882: (struct){ name: (int){ 9 } } 883: (struct){ name: (int){ 9 } } 884: (struct){ name: (int){ 9 } } 885: (struct){ name: (int){ 9 } } 886: (struct){ name: (int){ 9 } } 887: (struct){ name: (int){ 9 } } 888: (struct){ name: (int){ 9 } } 889: (struct){ name: (int){ 9 } } 890: (struct){ name: (int){ 9 } } 891: (struct){ name: (int){ 9 } } 892: (struct){ name: (int){ 9 } } 893: (struct){ name: (int){ 9 } } 894: (struct){ name: (int){ 9 } } 895: (struct){ name: (int){ 9 } } 896: (struct){ name: (int){ 9 } } 897: (struct){ name: (int){ 9 } } 898: (struct){ name: (int){ 9 } } 899: (struct){ name: (int){ 9 } } } } -- out/eval/stats -- Leaks: 0 Freed: 3927 Reused: 3921 Allocs: 6 Retain: 1 Unifications: 3927 Conjuncts: 4952 Disjuncts: 3928 cue-lang-cue-db9cc73/cue/testdata/builtins/000077500000000000000000000000001474664451600207165ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/builtins/056_issue314.txtar000066400000000000000000000063451474664451600237640ustar00rootroot00000000000000#name: issue314 #evalFull -- in.cue -- import ( "text/template" "encoding/yaml" "encoding/json" ) x: { s: "myname" #T } #T: { s: string out: template.Execute("{{.s}}", { "s": s }) } #V: { s: string out: json.Marshal({"s": s}) } #U: { s: string out: yaml.Marshal({"s": s}) } -- out/def -- import ( "encoding/json" "encoding/yaml" "text/template" ) x: { s: "myname" #T } #T: { s: string S = s out: template.Execute("{{.s}}", { s: S }) } #V: { s: string S658221 = s out: json.Marshal({ s: S658221 }) } #U: { s: string S629a0f = s out: yaml.Marshal({ s: S629a0f }) } -- out/export -- x: { s: "myname" out: "myname" } -- out/yaml -- x: s: myname out: myname -- out/json -- {"x":{"s":"myname","out":"myname"}} -- out/legacy-debug -- <0>{x: <1>C{s: "myname", out: "myname"}, #T: <2>C{s: string, out: <3>.Execute ("{{.s}}",<4>C{s: <5>.s})}, #V: <6>C{s: string, out: <7>.Marshal (<8>C{s: <9>.s})}, #U: <10>C{s: string, out: <11>.Marshal (<12>C{s: <13>.s})}} -- out/eval/stats -- Leaks: 0 Freed: 45 Reused: 39 Allocs: 6 Retain: 17 Unifications: 45 Conjuncts: 77 Disjuncts: 62 -- out/evalalpha -- (struct){ x: (#struct){ s: (string){ "myname" } out: (string){ "myname" } } #T: (#struct){ s: (string){ string } out: (_|_){ // [incomplete] #T.out: error in call to text/template.Execute: cannot convert non-concrete value string: // ./in.cue:14:7 // ./in.cue:13:2 } } #V: (#struct){ s: (string){ string } out: (_|_){ // [incomplete] cannot convert incomplete value "string" to JSON: // ./in.cue:20:7 } } #U: (#struct){ s: (string){ string } out: (_|_){ // [incomplete] #U.out: error in call to encoding/yaml.Marshal: incomplete value string: // ./in.cue:26:7 // ./in.cue:25:7 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -8,7 +8,7 @@ out: (_|_){ // [incomplete] #T.out: error in call to text/template.Execute: cannot convert non-concrete value string: // ./in.cue:14:7 - // ./in.cue:15:3 + // ./in.cue:13:2 } } #V: (#struct){ -- out/eval -- (struct){ x: (#struct){ s: (string){ "myname" } out: (string){ "myname" } } #T: (#struct){ s: (string){ string } out: (_|_){ // [incomplete] #T.out: error in call to text/template.Execute: cannot convert non-concrete value string: // ./in.cue:14:7 // ./in.cue:15:3 } } #V: (#struct){ s: (string){ string } out: (_|_){ // [incomplete] cannot convert incomplete value "string" to JSON: // ./in.cue:20:7 } } #U: (#struct){ s: (string){ string } out: (_|_){ // [incomplete] #U.out: error in call to encoding/yaml.Marshal: incomplete value string: // ./in.cue:26:7 // ./in.cue:25:7 } } } -- out/compile -- --- in.cue { x: { s: "myname" 〈1;#T〉 } #T: { s: string out: 〈import;"text/template"〉.Execute("{{.s}}", { s: 〈1;s〉 }) } #V: { s: string out: 〈import;"encoding/json"〉.Marshal({ s: 〈1;s〉 }) } #U: { s: string out: 〈import;"encoding/yaml"〉.Marshal({ s: 〈1;s〉 }) } } cue-lang-cue-db9cc73/cue/testdata/builtins/all.txtar000066400000000000000000000040351474664451600225540ustar00rootroot00000000000000-- in.cue -- fatalArg: { x: len("eee" + 'eee') } // don't call builtin for a permanent error of a child node fatalChild: { #b: {} x: and([{a: #b.c}]) } // allow incomplete child values. The error will persist after `and` is // evaluated down the line. This allows the and-ing of templates that may // complete later. okIncompleteChild: { b: {} x: and([{a: b.c}, {b: 1}]) } -- issue3412.cue -- andInPattern: { out: { [and(#constraints)]: _ someKey: {} } #constraints: [=~"^.*$"] } -- out/eval/stats -- Leaks: 2 Freed: 18 Reused: 12 Allocs: 8 Retain: 3 Unifications: 20 Conjuncts: 27 Disjuncts: 21 -- out/eval -- Errors: fatalArg.x: invalid operands "eee" and 'eee' to '+' (type string and bytes): ./in.cue:2:9 ./in.cue:2:17 fatalChild.x.a: undefined field: c: ./in.cue:8:17 Result: (_|_){ // [eval] fatalArg: (_|_){ // [eval] x: (_|_){ // [eval] fatalArg.x: invalid operands "eee" and 'eee' to '+' (type string and bytes): // ./in.cue:2:9 // ./in.cue:2:17 } } fatalChild: (_|_){ // [eval] #b: (#struct){ } x: (_|_){ // [eval] a: (_|_){ // [eval] fatalChild.x.a: undefined field: c: // ./in.cue:8:17 } } } okIncompleteChild: (struct){ b: (struct){ } x: (struct){ a: (_|_){ // [incomplete] okIncompleteChild.x.a: undefined field: c: // ./in.cue:16:16 } b: (int){ 1 } } } andInPattern: (struct){ out: (struct){ someKey: (struct){ } } #constraints: (#list){ 0: (string){ =~"^.*$" } } } } -- out/compile -- --- in.cue { fatalArg: { x: len(("eee" + 'eee')) } fatalChild: { #b: {} x: and([ { a: 〈2;#b〉.c }, ]) } okIncompleteChild: { b: {} x: and([ { a: 〈2;b〉.c }, { b: 1 }, ]) } } --- issue3412.cue { andInPattern: { out: { [and(〈1;#constraints〉)]: _ someKey: {} } #constraints: [ =~"^.*$", ] } } cue-lang-cue-db9cc73/cue/testdata/builtins/and.txtar000066400000000000000000000013121474664451600225410ustar00rootroot00000000000000-- in.cue -- merge: and([1, 1]) // ensure definitions along embedded scalars are preserved. embed: and([{2, #x: 1}, {2, #x: 2}]) -- out/eval/stats -- Leaks: 2 Freed: 4 Reused: 1 Allocs: 5 Retain: 2 Unifications: 6 Conjuncts: 13 Disjuncts: 6 -- out/eval -- Errors: embed.#x: conflicting values 2 and 1: ./in.cue:4:21 ./in.cue:4:33 Result: (_|_){ // [eval] merge: (int){ 1 } embed: (_|_){ // [eval] #x: (_|_){ // [eval] embed.#x: conflicting values 2 and 1: // ./in.cue:4:21 // ./in.cue:4:33 } } } -- out/compile -- --- in.cue { merge: and([ 1, 1, ]) embed: and([ { 2 #x: 1 }, { 2 #x: 2 }, ]) } cue-lang-cue-db9cc73/cue/testdata/builtins/args.txtar000066400000000000000000000017221474664451600227400ustar00rootroot00000000000000-- in.cue -- import ( "math" "strings" ) issue3584: reduced: t1: { ref: out trigger: *1 | 2 out: strings.SliceRunes("ABC", 0, trigger) } issue3584: reduced: t2: { x: math.Abs(y) y: *6 | 5 } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 5 Allocs: 9 Retain: 1 Unifications: 10 Conjuncts: 17 Disjuncts: 15 -- out/eval -- (struct){ issue3584: (struct){ reduced: (struct){ t1: (struct){ ref: (string){ "A" } trigger: (int){ |(*(int){ 1 }, (int){ 2 }) } out: (string){ "A" } } t2: (struct){ x: (int){ 6 } y: (int){ |(*(int){ 6 }, (int){ 5 }) } } } } } -- out/compile -- --- in.cue { issue3584: { reduced: { t1: { ref: 〈0;out〉 trigger: (*1|2) out: 〈import;strings〉.SliceRunes("ABC", 0, 〈0;trigger〉) } } } issue3584: { reduced: { t2: { x: 〈import;math〉.Abs(〈0;y〉) y: (*6|5) } } } } cue-lang-cue-db9cc73/cue/testdata/builtins/closed.txtar000066400000000000000000000264621474664451600232650ustar00rootroot00000000000000-- in.cue -- a: close({ a: b: int }) b: a & {x: int} // err c: a & {a: c: int} // okay (non-recursive close) inDisjunctions: { x: [string]: #Def #Def: [string]: { a: b: true let X = a close({uint: a: b: X.b}) | close({string: a: b: true}) } x: socket: string: {} x: syslog: x.socket x: syslog: xxx: {} } issue642: { test: close({ a: _ b: x: _ } & { [string]: y: _ }) test: a: x: _ test: b: x: _ } // Issue 642 withSubfields: { test: close({ a: _ b: x: _ [string]: y: _ }) test: a: x: _ test: b: x: _ } issue3572: { t1: close({...}) & {a: 5} e: close({...}) t2: e & {a: 5} } issue3580: { x: close({ a: _ b: x.a }) } -- out/evalalpha/stats -- Leaks: 372 Freed: 6 Reused: 6 Allocs: 372 Retain: 0 Unifications: 179 Conjuncts: 922 Disjuncts: 24 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 43 -Freed: 170 -Reused: 164 -Allocs: 49 -Retain: 44 +Leaks: 372 +Freed: 6 +Reused: 6 +Allocs: 372 +Retain: 0 -Unifications: 199 -Conjuncts: 389 -Disjuncts: 204 +Unifications: 179 +Conjuncts: 922 +Disjuncts: 24 -- out/eval/stats -- Leaks: 43 Freed: 170 Reused: 164 Allocs: 49 Retain: 44 Unifications: 199 Conjuncts: 389 Disjuncts: 204 -- out/evalalpha -- Errors: b.x: field not allowed: ./in.cue:1:4 ./in.cue:5:9 Result: (_|_){ // [eval] a: (#struct){ a: (struct){ b: (int){ int } } } b: (_|_){ // [eval] x: (_|_){ // [eval] b.x: field not allowed: // ./in.cue:1:4 // ./in.cue:5:9 } a: (struct){ b: (int){ int } } } c: (#struct){ a: (struct){ c: (int){ int } b: (int){ int } } } inDisjunctions: (struct){ x: (struct){ socket: (#struct){ string: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } } let X#1 = ~(inDisjunctions.x.socket.string.a) uint: (#struct){ a: (#struct){ b: (bool){ true } } } }, (#struct){ a: (#struct){ b: (bool){ true } } let X#1 = ~(inDisjunctions.x.socket.string.a) string: (#struct){ a: (#struct){ b: (bool){ true } } } }) } } syslog: (#struct){ xxx: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 uint: (#struct){ a: (#struct){ b: (bool){ true } } } }, (#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 string: (#struct){ a: (#struct){ b: (bool){ true } } } }) } string: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 uint: (#struct){ a: (#struct){ b: (bool){ true } } } }, (#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 string: (#struct){ a: (#struct){ b: (bool){ true } } } }) } } } #Def: (#struct){ } } issue642: (struct){ test: (#struct){ a: (struct){ x: (_){ _ } y: (_){ _ } } b: (struct){ x: (_){ _ } y: (_){ _ } } } } withSubfields: (struct){ test: (#struct){ a: (struct){ x: (_){ _ } y: (_){ _ } } b: (struct){ x: (_){ _ } y: (_){ _ } } } } issue3572: (struct){ t1: (#struct){ a: (int){ 5 } } e: (#struct){ } t2: (#struct){ a: (int){ 5 } } } issue3580: (struct){ x: (#struct){ a: (_){ _ } b: (_){ _ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,6 @@ Errors: b.x: field not allowed: - ./in.cue:1:10 - ./in.cue:5:4 + ./in.cue:1:4 ./in.cue:5:9 Result: @@ -14,20 +13,19 @@ } b: (_|_){ // [eval] - a: (struct){ - b: (int){ int } - } x: (_|_){ // [eval] b.x: field not allowed: - // ./in.cue:1:10 - // ./in.cue:5:4 + // ./in.cue:1:4 // ./in.cue:5:9 } + a: (struct){ + b: (int){ int } + } } c: (#struct){ a: (struct){ - b: (int){ int } c: (int){ int } + b: (int){ int } } } inDisjunctions: (struct){ @@ -37,21 +35,17 @@ a: (#struct){ b: (bool){ true } } - let X#1 = (#struct){ - b: (bool){ true } - } - uint: (#struct){ - a: (#struct){ - b: (bool){ true } - } - } - }, (#struct){ - a: (#struct){ - b: (bool){ true } - } - let X#1 = (#struct){ - b: (bool){ true } - } + let X#1 = ~(inDisjunctions.x.socket.string.a) + uint: (#struct){ + a: (#struct){ + b: (bool){ true } + } + } + }, (#struct){ + a: (#struct){ + b: (bool){ true } + } + let X#1 = ~(inDisjunctions.x.socket.string.a) string: (#struct){ a: (#struct){ b: (bool){ true } @@ -60,27 +54,6 @@ }) } } syslog: (#struct){ - string: (#struct){ |((#struct){ - a: (#struct){ - b: (bool){ true } - } - let X#1multi = 〈0;a〉 - uint: (#struct){ - a: (#struct){ - b: (bool){ true } - } - } - }, (#struct){ - a: (#struct){ - b: (bool){ true } - } - let X#1multi = 〈0;a〉 - string: (#struct){ - a: (#struct){ - b: (bool){ true } - } - } - }) } xxx: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } @@ -102,6 +75,27 @@ } } }) } + string: (#struct){ |((#struct){ + a: (#struct){ + b: (bool){ true } + } + let X#1multi = 〈0;a〉 + uint: (#struct){ + a: (#struct){ + b: (bool){ true } + } + } + }, (#struct){ + a: (#struct){ + b: (bool){ true } + } + let X#1multi = 〈0;a〉 + string: (#struct){ + a: (#struct){ + b: (bool){ true } + } + } + }) } } } #Def: (#struct){ -- diff/todo/p3 -- Reordering Let differs. -- out/eval -- Errors: b.x: field not allowed: ./in.cue:1:10 ./in.cue:5:4 ./in.cue:5:9 Result: (_|_){ // [eval] a: (#struct){ a: (struct){ b: (int){ int } } } b: (_|_){ // [eval] a: (struct){ b: (int){ int } } x: (_|_){ // [eval] b.x: field not allowed: // ./in.cue:1:10 // ./in.cue:5:4 // ./in.cue:5:9 } } c: (#struct){ a: (struct){ b: (int){ int } c: (int){ int } } } inDisjunctions: (struct){ x: (struct){ socket: (#struct){ string: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } } let X#1 = (#struct){ b: (bool){ true } } uint: (#struct){ a: (#struct){ b: (bool){ true } } } }, (#struct){ a: (#struct){ b: (bool){ true } } let X#1 = (#struct){ b: (bool){ true } } string: (#struct){ a: (#struct){ b: (bool){ true } } } }) } } syslog: (#struct){ string: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 uint: (#struct){ a: (#struct){ b: (bool){ true } } } }, (#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 string: (#struct){ a: (#struct){ b: (bool){ true } } } }) } xxx: (#struct){ |((#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 uint: (#struct){ a: (#struct){ b: (bool){ true } } } }, (#struct){ a: (#struct){ b: (bool){ true } } let X#1multi = 〈0;a〉 string: (#struct){ a: (#struct){ b: (bool){ true } } } }) } } } #Def: (#struct){ } } issue642: (struct){ test: (#struct){ a: (struct){ x: (_){ _ } y: (_){ _ } } b: (struct){ x: (_){ _ } y: (_){ _ } } } } withSubfields: (struct){ test: (#struct){ a: (struct){ x: (_){ _ } y: (_){ _ } } b: (struct){ x: (_){ _ } y: (_){ _ } } } } issue3572: (struct){ t1: (#struct){ a: (int){ 5 } } e: (#struct){ } t2: (#struct){ a: (int){ 5 } } } issue3580: (struct){ x: (#struct){ a: (_){ _ } b: (_){ _ } } } } -- out/compile -- --- in.cue { a: close({ a: { b: int } }) b: (〈0;a〉 & { x: int }) c: (〈0;a〉 & { a: { c: int } }) inDisjunctions: { x: { [string]: 〈1;#Def〉 } #Def: { [string]: { a: { b: true } let X#1 = 〈0;a〉 (close({ uint: { a: { b: 〈3;let X#1〉.b } } })|close({ string: { a: { b: true } } })) } } x: { socket: { string: {} } } x: { syslog: 〈1;x〉.socket } x: { syslog: { xxx: {} } } } issue642: { test: close(({ a: _ b: { x: _ } } & { [string]: { y: _ } })) test: { a: { x: _ } } test: { b: { x: _ } } } withSubfields: { test: close({ a: _ b: { x: _ } [string]: { y: _ } }) test: { a: { x: _ } } test: { b: { x: _ } } } issue3572: { t1: (close({ ... }) & { a: 5 }) e: close({ ... }) t2: (〈0;e〉 & { a: 5 }) } issue3580: { x: close({ a: _ b: 〈1;x〉.a }) } } cue-lang-cue-db9cc73/cue/testdata/builtins/default.txtar000066400000000000000000000023011474664451600234220ustar00rootroot00000000000000-- in.cue -- import ( "list" "strings" "text/template" ) Len: len(*[1, 2, 3] | 0) Close: close(*{} | 0) And: and(*[1, 1] | int) Or: or(*[1, 1] | int) Div: div(*5 | string, 2) Mod: mod(*5 | string, 2) Quo: quo(*5 | string, 2) Rem: rem(*5 | string, 2) -- out/compile -- --- in.cue { Len: len((*[ 1, 2, 3, ]|0)) Close: close((*{}|0)) And: and((*[ 1, 1, ]|int)) Or: or((*[ 1, 1, ]|int)) Div: div((*5|string), 2) Mod: mod((*5|string), 2) Quo: quo((*5|string), 2) Rem: rem((*5|string), 2) } -- out/eval/stats -- Leaks: 0 Freed: 45 Reused: 40 Allocs: 5 Retain: 0 Unifications: 25 Conjuncts: 52 Disjuncts: 45 -- out/evalalpha -- (struct){ Len: (int){ 3 } Close: (#struct){ } And: (int){ 1 } Or: (int){ 1 } Div: (int){ 2 } Mod: (int){ 1 } Quo: (int){ 2 } Rem: (int){ 1 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,6 +1,6 @@ (struct){ Len: (int){ 3 } - Close: (struct){ + Close: (#struct){ } And: (int){ 1 } Or: (int){ 1 } -- out/eval -- (struct){ Len: (int){ 3 } Close: (struct){ } And: (int){ 1 } Or: (int){ 1 } Div: (int){ 2 } Mod: (int){ 1 } Quo: (int){ 2 } Rem: (int){ 1 } } cue-lang-cue-db9cc73/cue/testdata/builtins/incomplete.txtar000066400000000000000000000363041474664451600241470ustar00rootroot00000000000000-- in.cue -- import ( "list" "strings" "text/template" ) list1: { // Note that Top is not incomplete, only its first element is. // We allow FlattenN to proceed and pass on the incomplete values. Out1: list.FlattenN(Top, 1) Out2: [...] & list.FlattenN(Top, 1) Out3: list.FlattenN(Top, 1) & [...] // This evaluates to a list with an incomplete element. Top: [ [for _, F in _Sub {F}], ] _Sub: a.b a: {} // b does not } list2: { Out1: list.FlattenN(_Top, 1) Out2: [...] & list.FlattenN(_Top, 1) Out3: list.FlattenN(_Top, 1) & [...] // This evaluates to a list with an incomplete element. _Top: [ for _, F in #Sub {F}, ] #Sub: a.b a: {} // b does not } value1: { a: len('sf' | 'dd') } value2: { len('sf' | 'dd') } incompleteArgDecimalList: { a: #a & {param: 123} #a: { param: int transformed: +param max: list.Max([transformed]) } } incompleteArgStringList: { a: #a & {param: "123"} #a: { param: string transformed: param + "" joined: strings.Join([transformed], "-") } } incompleteList: { x: _ decimal: list.Max(x) str: strings.Join(x, "") } // TODO: add better error positions. incompleteListError: { x: y + [] y: _ decimal: list.Max(x) str: strings.Join(x, "") } badListType: { x: 2 decimal: list.Max(x) str: strings.Join(x, "") } badListError: { x: 2 + y y: "foo" decimal: list.Max(x) str: strings.Join(x, "") } // Issue #1095 // Preserve combined error severity for multiple errors. multipleErrors: { #T: { params: { x: string y: string } out: template.Execute("{{.x}} {{.y}}", params) } } -- out/eval/stats -- Leaks: 8 Freed: 115 Reused: 110 Allocs: 13 Retain: 58 Unifications: 103 Conjuncts: 255 Disjuncts: 150 -- out/evalalpha -- Errors: badListType.decimal: cannot use 2 (type int) as list in argument 1 to list.Max: ./in.cue:79:11 badListType.str: cannot use 2 (type int) as list in argument 1 to strings.Join: ./in.cue:79:11 badListError.x: invalid operands 2 and "foo" to '+' (type int and string): ./in.cue:85:11 ./in.cue:86:11 Result: (_|_){ // [eval] list1: (struct){ Out1: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } Out2: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } Out3: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } Top: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } _Sub: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } a: (struct){ } } list2: (struct){ Out1: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } Out2: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } Out3: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } _Top: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } #Sub: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } a: (struct){ } } value1: (struct){ a: (_|_){ // [incomplete] value1.a: unresolved disjunction 'sf' | 'dd' (type bytes): // ./in.cue:39:5 } } value2: (_|_){ // [incomplete] value2: unresolved disjunction 'sf' | 'dd' (type bytes): // ./in.cue:43:2 } incompleteArgDecimalList: (struct){ a: (#struct){ param: (int){ 123 } transformed: (int){ 123 } max: (int){ 123 } } #a: (#struct){ param: (int){ int } transformed: (_|_){ // [incomplete] incompleteArgDecimalList.#a.transformed: operand param of '+' not concrete (was int): // ./in.cue:50:17 } max: (_|_){ // [incomplete] incompleteArgDecimalList.#a.transformed: operand param of '+' not concrete (was int): // ./in.cue:50:17 } } } incompleteArgStringList: (struct){ a: (#struct){ param: (string){ "123" } transformed: (string){ "123" } joined: (string){ "123" } } #a: (#struct){ param: (string){ string } transformed: (_|_){ // [incomplete] incompleteArgStringList.#a.transformed: non-concrete value string in operand to +: // ./in.cue:59:16 // ./in.cue:58:16 } joined: (_|_){ // [incomplete] incompleteArgStringList.#a.transformed: non-concrete value string in operand to +: // ./in.cue:59:16 // ./in.cue:58:16 } } } incompleteList: (struct){ x: (_){ _ } decimal: (_|_){ // [incomplete] incompleteList.decimal: non-concrete list for argument 0: // ./in.cue:66:11 } str: (_|_){ // [incomplete] incompleteList.str: non-concrete list for argument 0: // ./in.cue:67:11 } } incompleteListError: (struct){ x: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 // ./in.cue:73:11 } y: (_){ _ } decimal: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 // ./in.cue:73:11 } str: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 // ./in.cue:73:11 } } badListType: (_|_){ // [eval] x: (int){ 2 } decimal: (_|_){ // [eval] badListType.decimal: cannot use 2 (type int) as list in argument 1 to list.Max: // ./in.cue:79:11 } str: (_|_){ // [eval] badListType.str: cannot use 2 (type int) as list in argument 1 to strings.Join: // ./in.cue:79:11 } } badListError: (_|_){ // [eval] x: (_|_){ // [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string): // ./in.cue:85:11 // ./in.cue:86:11 } y: (string){ "foo" } decimal: (_|_){ // [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string): // ./in.cue:85:11 // ./in.cue:86:11 } str: (_|_){ // [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string): // ./in.cue:85:11 // ./in.cue:86:11 } } multipleErrors: (struct){ #T: (#struct){ params: (#struct){ x: (string){ string } y: (string){ string } } out: (_|_){ // [incomplete] multipleErrors.#T.out: error in call to text/template.Execute: cannot convert non-concrete value string: // ./in.cue:99:8 // ./in.cue:96:4 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -89,7 +89,7 @@ // ./in.cue:50:17 } max: (_|_){ - // [incomplete] incompleteArgDecimalList.#a.0: operand param of '+' not concrete (was int): + // [incomplete] incompleteArgDecimalList.#a.transformed: operand param of '+' not concrete (was int): // ./in.cue:50:17 } } @@ -108,7 +108,7 @@ // ./in.cue:58:16 } joined: (_|_){ - // [incomplete] incompleteArgStringList.#a.0: non-concrete value string in operand to +: + // [incomplete] incompleteArgStringList.#a.transformed: non-concrete value string in operand to +: // ./in.cue:59:16 // ./in.cue:58:16 } @@ -129,15 +129,18 @@ x: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 + // ./in.cue:73:11 } y: (_){ _ } decimal: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 - } - str: (_|_){ - // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: - // ./in.cue:72:11 + // ./in.cue:73:11 + } + str: (_|_){ + // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: + // ./in.cue:72:11 + // ./in.cue:73:11 } } badListType: (_|_){ -- out/eval -- Errors: badListType.decimal: cannot use 2 (type int) as list in argument 1 to list.Max: ./in.cue:79:11 badListType.str: cannot use 2 (type int) as list in argument 1 to strings.Join: ./in.cue:79:11 badListError.x: invalid operands 2 and "foo" to '+' (type int and string): ./in.cue:85:11 ./in.cue:86:11 Result: (_|_){ // [eval] list1: (struct){ Out1: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } Out2: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } Out3: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } Top: (#list){ 0: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } } _Sub: (_|_){ // [incomplete] list1._Sub: undefined field: b: // ./in.cue:19:10 } a: (struct){ } } list2: (struct){ Out1: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } Out2: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } Out3: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } _Top: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } #Sub: (_|_){ // [incomplete] list2.#Sub: undefined field: b: // ./in.cue:33:10 } a: (struct){ } } value1: (struct){ a: (_|_){ // [incomplete] value1.a: unresolved disjunction 'sf' | 'dd' (type bytes): // ./in.cue:39:5 } } value2: (_|_){ // [incomplete] value2: unresolved disjunction 'sf' | 'dd' (type bytes): // ./in.cue:43:2 } incompleteArgDecimalList: (struct){ a: (#struct){ param: (int){ 123 } transformed: (int){ 123 } max: (int){ 123 } } #a: (#struct){ param: (int){ int } transformed: (_|_){ // [incomplete] incompleteArgDecimalList.#a.transformed: operand param of '+' not concrete (was int): // ./in.cue:50:17 } max: (_|_){ // [incomplete] incompleteArgDecimalList.#a.0: operand param of '+' not concrete (was int): // ./in.cue:50:17 } } } incompleteArgStringList: (struct){ a: (#struct){ param: (string){ "123" } transformed: (string){ "123" } joined: (string){ "123" } } #a: (#struct){ param: (string){ string } transformed: (_|_){ // [incomplete] incompleteArgStringList.#a.transformed: non-concrete value string in operand to +: // ./in.cue:59:16 // ./in.cue:58:16 } joined: (_|_){ // [incomplete] incompleteArgStringList.#a.0: non-concrete value string in operand to +: // ./in.cue:59:16 // ./in.cue:58:16 } } } incompleteList: (struct){ x: (_){ _ } decimal: (_|_){ // [incomplete] incompleteList.decimal: non-concrete list for argument 0: // ./in.cue:66:11 } str: (_|_){ // [incomplete] incompleteList.str: non-concrete list for argument 0: // ./in.cue:67:11 } } incompleteListError: (struct){ x: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 } y: (_){ _ } decimal: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 } str: (_|_){ // [incomplete] incompleteListError.x: non-concrete value _ in operand to +: // ./in.cue:72:11 } } badListType: (_|_){ // [eval] x: (int){ 2 } decimal: (_|_){ // [eval] badListType.decimal: cannot use 2 (type int) as list in argument 1 to list.Max: // ./in.cue:79:11 } str: (_|_){ // [eval] badListType.str: cannot use 2 (type int) as list in argument 1 to strings.Join: // ./in.cue:79:11 } } badListError: (_|_){ // [eval] x: (_|_){ // [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string): // ./in.cue:85:11 // ./in.cue:86:11 } y: (string){ "foo" } decimal: (_|_){ // [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string): // ./in.cue:85:11 // ./in.cue:86:11 } str: (_|_){ // [eval] badListError.x: invalid operands 2 and "foo" to '+' (type int and string): // ./in.cue:85:11 // ./in.cue:86:11 } } multipleErrors: (struct){ #T: (#struct){ params: (#struct){ x: (string){ string } y: (string){ string } } out: (_|_){ // [incomplete] multipleErrors.#T.out: error in call to text/template.Execute: cannot convert non-concrete value string: // ./in.cue:99:8 // ./in.cue:96:4 } } } } -- out/compile -- --- in.cue { list1: { Out1: 〈import;list〉.FlattenN(〈0;Top〉, 1) Out2: ([ ..., ] & 〈import;list〉.FlattenN(〈0;Top〉, 1)) Out3: (〈import;list〉.FlattenN(〈0;Top〉, 1) & [ ..., ]) Top: [ [ for _, F in 〈2;_Sub〉 { 〈1;F〉 }, ], ] _Sub: 〈0;a〉.b a: {} } list2: { Out1: 〈import;list〉.FlattenN(〈0;_Top〉, 1) Out2: ([ ..., ] & 〈import;list〉.FlattenN(〈0;_Top〉, 1)) Out3: (〈import;list〉.FlattenN(〈0;_Top〉, 1) & [ ..., ]) _Top: [ for _, F in 〈1;#Sub〉 { 〈1;F〉 }, ] #Sub: 〈0;a〉.b a: {} } value1: { a: len(('sf'|'dd')) } value2: { len(('sf'|'dd')) } incompleteArgDecimalList: { a: (〈0;#a〉 & { param: 123 }) #a: { param: int transformed: +〈0;param〉 max: 〈import;list〉.Max([ 〈1;transformed〉, ]) } } incompleteArgStringList: { a: (〈0;#a〉 & { param: "123" }) #a: { param: string transformed: (〈0;param〉 + "") joined: 〈import;strings〉.Join([ 〈1;transformed〉, ], "-") } } incompleteList: { x: _ decimal: 〈import;list〉.Max(〈0;x〉) str: 〈import;strings〉.Join(〈0;x〉, "") } incompleteListError: { x: (〈0;y〉 + []) y: _ decimal: 〈import;list〉.Max(〈0;x〉) str: 〈import;strings〉.Join(〈0;x〉, "") } badListType: { x: 2 decimal: 〈import;list〉.Max(〈0;x〉) str: 〈import;strings〉.Join(〈0;x〉, "") } badListError: { x: (2 + 〈0;y〉) y: "foo" decimal: 〈import;list〉.Max(〈0;x〉) str: 〈import;strings〉.Join(〈0;x〉, "") } multipleErrors: { #T: { params: { x: string y: string } out: 〈import;"text/template"〉.Execute("{{.x}} {{.y}}", 〈0;params〉) } } } cue-lang-cue-db9cc73/cue/testdata/builtins/intdiv.txtar000066400000000000000000000103311474664451600232750ustar00rootroot00000000000000-- in.cue -- quo1: quo(5, 2) // 2 quo2: quo(5, -2) // -2 quo3: quo(-5, 2) // -2 quo4: quo(-5, -2) // 2 quoDivByZero: quo(2, 0) quoTypeError1: quo(2.0, 1) quoTypeError2: quo(2, 1.0) rem1: rem(5, 2) // 1 rem2: rem(5, -2) // 1 rem3: rem(-5, 2) // -1 rem4: rem(-5, -2) // -1 remDivByZero: rem(2, 0) remTypeError1: rem(2.0, 1) remTypeError2: rem(2, 1.0) div1: div(5, 2) // 2 div2: div(5, -2) // -2 div3: div(-5, 2) // -3 div4: div(-5, -2) // 3 divDivByZero: div(2, 0) divTypeError1: div(2.0, 1) divTypeError2: div(2, 1.0) mod1: mod(5, 2) // 1 mod2: mod(5, -2) // 1 mod3: mod(-5, 2) // 1 mod4: mod(-5, -2) // 1 modDivByZero: mod(2, 0) modTypeError1: mod(2.0, 1) modTypeError2: mod(2, 1.0) -- out/eval/stats -- Leaks: 0 Freed: 29 Reused: 27 Allocs: 2 Retain: 0 Unifications: 29 Conjuncts: 29 Disjuncts: 29 -- out/eval -- Errors: quoDivByZero: division by zero: ./in.cue:6:15 quoTypeError1: cannot use 2.0 (type float) as int in argument 1 to quo: ./in.cue:8:20 quoTypeError2: cannot use 1.0 (type float) as int in argument 2 to quo: ./in.cue:9:23 remDivByZero: division by zero: ./in.cue:16:15 remTypeError1: cannot use 2.0 (type float) as int in argument 1 to rem: ./in.cue:18:20 remTypeError2: cannot use 1.0 (type float) as int in argument 2 to rem: ./in.cue:19:23 divDivByZero: division by zero: ./in.cue:26:15 divTypeError1: cannot use 2.0 (type float) as int in argument 1 to div: ./in.cue:28:20 divTypeError2: cannot use 1.0 (type float) as int in argument 2 to div: ./in.cue:29:23 modDivByZero: division by zero: ./in.cue:36:15 modTypeError1: cannot use 2.0 (type float) as int in argument 1 to mod: ./in.cue:38:20 modTypeError2: cannot use 1.0 (type float) as int in argument 2 to mod: ./in.cue:39:23 Result: (_|_){ // [eval] quo1: (int){ 2 } quo2: (int){ -2 } quo3: (int){ -2 } quo4: (int){ 2 } quoDivByZero: (_|_){ // [eval] quoDivByZero: division by zero: // ./in.cue:6:15 } quoTypeError1: (_|_){ // [eval] quoTypeError1: cannot use 2.0 (type float) as int in argument 1 to quo: // ./in.cue:8:20 } quoTypeError2: (_|_){ // [eval] quoTypeError2: cannot use 1.0 (type float) as int in argument 2 to quo: // ./in.cue:9:23 } rem1: (int){ 1 } rem2: (int){ 1 } rem3: (int){ -1 } rem4: (int){ -1 } remDivByZero: (_|_){ // [eval] remDivByZero: division by zero: // ./in.cue:16:15 } remTypeError1: (_|_){ // [eval] remTypeError1: cannot use 2.0 (type float) as int in argument 1 to rem: // ./in.cue:18:20 } remTypeError2: (_|_){ // [eval] remTypeError2: cannot use 1.0 (type float) as int in argument 2 to rem: // ./in.cue:19:23 } div1: (int){ 2 } div2: (int){ -2 } div3: (int){ -3 } div4: (int){ 3 } divDivByZero: (_|_){ // [eval] divDivByZero: division by zero: // ./in.cue:26:15 } divTypeError1: (_|_){ // [eval] divTypeError1: cannot use 2.0 (type float) as int in argument 1 to div: // ./in.cue:28:20 } divTypeError2: (_|_){ // [eval] divTypeError2: cannot use 1.0 (type float) as int in argument 2 to div: // ./in.cue:29:23 } mod1: (int){ 1 } mod2: (int){ 1 } mod3: (int){ 1 } mod4: (int){ 1 } modDivByZero: (_|_){ // [eval] modDivByZero: division by zero: // ./in.cue:36:15 } modTypeError1: (_|_){ // [eval] modTypeError1: cannot use 2.0 (type float) as int in argument 1 to mod: // ./in.cue:38:20 } modTypeError2: (_|_){ // [eval] modTypeError2: cannot use 1.0 (type float) as int in argument 2 to mod: // ./in.cue:39:23 } } -- out/compile -- --- in.cue { quo1: quo(5, 2) quo2: quo(5, -2) quo3: quo(-5, 2) quo4: quo(-5, -2) quoDivByZero: quo(2, 0) quoTypeError1: quo(2.0, 1) quoTypeError2: quo(2, 1.0) rem1: rem(5, 2) rem2: rem(5, -2) rem3: rem(-5, 2) rem4: rem(-5, -2) remDivByZero: rem(2, 0) remTypeError1: rem(2.0, 1) remTypeError2: rem(2, 1.0) div1: div(5, 2) div2: div(5, -2) div3: div(-5, 2) div4: div(-5, -2) divDivByZero: div(2, 0) divTypeError1: div(2.0, 1) divTypeError2: div(2, 1.0) mod1: mod(5, 2) mod2: mod(5, -2) mod3: mod(-5, 2) mod4: mod(-5, -2) modDivByZero: mod(2, 0) modTypeError1: mod(2.0, 1) modTypeError2: mod(2, 1.0) } cue-lang-cue-db9cc73/cue/testdata/builtins/issue299.txtar000066400000000000000000000014361474664451600234020ustar00rootroot00000000000000-- in.cue -- import "list" x: list.UniqueItems x: [string, ...string] x: ["x", "x"] -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 0 Unifications: 2 Conjuncts: 5 Disjuncts: 3 -- out/eval -- Errors: x: invalid value ["x","x"] (does not satisfy list.UniqueItems): equal value ("x") at position 0 and 1: ./in.cue:3:4 ./in.cue:4:4 ./in.cue:5:4 Result: (_|_){ // [eval] x: (_|_){ // [eval] x: invalid value ["x","x"] (does not satisfy list.UniqueItems): equal value ("x") at position 0 and 1: // ./in.cue:3:4 // ./in.cue:4:4 // ./in.cue:5:4 0: (string){ "x" } 1: (string){ "x" } } } -- out/compile -- --- in.cue { x: 〈import;list〉.UniqueItems x: [ string, ...string, ] x: [ "x", "x", ] } cue-lang-cue-db9cc73/cue/testdata/builtins/issue490.txtar000066400000000000000000000031411474664451600233660ustar00rootroot00000000000000-- test.cue -- A: close({ a: 1 b: 2 }) B: A & { c: 3 } -- out/eval/stats -- Leaks: 2 Freed: 8 Reused: 5 Allocs: 5 Retain: 2 Unifications: 10 Conjuncts: 14 Disjuncts: 10 -- out/evalalpha -- Errors: B.c: field not allowed: ./test.cue:1:4 ./test.cue:7:2 Result: (_|_){ // [eval] A: (#struct){ a: (int){ 1 } b: (int){ 2 } } B: (_|_){ // [eval] c: (_|_){ // [eval] B.c: field not allowed: // ./test.cue:1:4 // ./test.cue:7:2 } a: (int){ 1 } b: (int){ 2 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,6 @@ Errors: B.c: field not allowed: - ./test.cue:1:10 - ./test.cue:6:4 + ./test.cue:1:4 ./test.cue:7:2 Result: @@ -13,13 +12,12 @@ } B: (_|_){ // [eval] - a: (int){ 1 } - b: (int){ 2 } c: (_|_){ // [eval] B.c: field not allowed: - // ./test.cue:1:10 - // ./test.cue:6:4 + // ./test.cue:1:4 // ./test.cue:7:2 } + a: (int){ 1 } + b: (int){ 2 } } } -- diff/todo/p2 -- positions -- diff/todo/p3 -- Reordering -- out/eval -- Errors: B.c: field not allowed: ./test.cue:1:10 ./test.cue:6:4 ./test.cue:7:2 Result: (_|_){ // [eval] A: (#struct){ a: (int){ 1 } b: (int){ 2 } } B: (_|_){ // [eval] a: (int){ 1 } b: (int){ 2 } c: (_|_){ // [eval] B.c: field not allowed: // ./test.cue:1:10 // ./test.cue:6:4 // ./test.cue:7:2 } } } -- out/compile -- --- test.cue { A: close({ a: 1 b: 2 }) B: (〈0;A〉 & { c: 3 }) } cue-lang-cue-db9cc73/cue/testdata/builtins/issue_3567.txtar000066400000000000000000000023321474664451600236160ustar00rootroot00000000000000-- in.cue -- import "strings" a: strings.Join( [ strings.Join(["1"]), "2" ], "\n") -- out/compile -- --- in.cue { a: 〈import;strings〉.Join([ 〈import;strings〉.Join([ "1", ]), "2", ], "\n") } -- out/eval/stats -- Leaks: 1 Freed: 5 Reused: 1 Allocs: 5 Retain: 2 Unifications: 6 Conjuncts: 6 Disjuncts: 7 -- out/evalalpha -- Errors: 0: not enough arguments in call to strings.Join (have 1, want 2): ./in.cue:2:20 Result: (_|_){ // [eval] a: (_|_){ // [eval] 0: not enough arguments in call to strings.Join (have 1, want 2): // ./in.cue:2:20 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,6 +1,12 @@ +Errors: +0: not enough arguments in call to strings.Join (have 1, want 2): + ./in.cue:2:20 + +Result: (_|_){ // [eval] a: (_|_){ - // [eval] + // [eval] 0: not enough arguments in call to strings.Join (have 1, want 2): + // ./in.cue:2:20 } } -- diff/explanation -- The old evaluator does not correctly handle the nested nature of calls to strings.Join, and buries the error of the missing argument in the nested call. The new evaluator handles this properly. -- out/eval -- (_|_){ // [eval] a: (_|_){ // [eval] } } cue-lang-cue-db9cc73/cue/testdata/builtins/list/000077500000000000000000000000001474664451600216715ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/builtins/list/issue332.txtar000066400000000000000000000015271474664451600243420ustar00rootroot00000000000000-- in.cue -- import "list" #d: { #x: string result: [#x] } #foo: { X=#x: _ y: list.FlattenN((#d & {#x: X}).result, 1) } r: #foo & { #x: "hello" } -- out/eval/stats -- Leaks: 2 Freed: 19 Reused: 13 Allocs: 8 Retain: 10 Unifications: 21 Conjuncts: 52 Disjuncts: 29 -- out/eval -- (struct){ #d: (#struct){ #x: (string){ string } result: (#list){ 0: (string){ string } } } #foo: (#struct){ #x: (_){ _ } y: (#list){ 0: (string){ string } } } r: (#struct){ #x: (string){ "hello" } y: (#list){ 0: (string){ "hello" } } } } -- out/compile -- --- in.cue { #d: { #x: string result: [ 〈1;#x〉, ] } #foo: { #x: _ y: 〈import;list〉.FlattenN((〈1;#d〉 & { #x: 〈1;#x〉 }).result, 1) } r: (〈0;#foo〉 & { #x: "hello" }) } cue-lang-cue-db9cc73/cue/testdata/builtins/list/sort.txtar000066400000000000000000000007371474664451600237530ustar00rootroot00000000000000-- in.cue -- import "list" a: list.Sort([2, 3, 1, 4], {x: _, y: _, less: x < y}) -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 10 Allocs: 5 Retain: 2 Unifications: 15 Conjuncts: 24 Disjuncts: 17 -- out/eval -- (struct){ a: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } 3: (int){ 4 } } } -- out/compile -- --- in.cue { a: 〈import;list〉.Sort([ 2, 3, 1, 4, ], { x: _ y: _ less: (〈0;x〉 < 〈0;y〉) }) } cue-lang-cue-db9cc73/cue/testdata/builtins/matchif.txtar000066400000000000000000000056771474664451600234340ustar00rootroot00000000000000-- in.cue -- regularFields: { [_]: matchIf({x!: >2}, {y!: 5}, {y!: 1}) ok1: {x: 10, y: 5} ok2: {x: 11, y: 5} ok3: {x: 2, y: 1} ok4: {x: 1, y: 1} err1: {x: 10, y: 6} err2: {x: 11, y: 6} err3: {x: 2, y: 5} err4: {x: 1, y: 2} } -- out/eval/stats -- Leaks: 24 Freed: 74 Reused: 69 Allocs: 29 Retain: 24 Unifications: 98 Conjuncts: 154 Disjuncts: 98 -- out/eval -- Errors: regularFields.err1: invalid value {x:10,y:6} (does not satisfy matchIf): conflicting values 5 and 6: ./in.cue:2:7 ./in.cue:2:30 ./in.cue:7:8 ./in.cue:7:19 regularFields.err2: invalid value {x:11,y:6} (does not satisfy matchIf): conflicting values 5 and 6: ./in.cue:2:7 ./in.cue:2:30 ./in.cue:8:8 ./in.cue:8:19 regularFields.err3: invalid value {x:2,y:5} (does not satisfy matchIf): conflicting values 1 and 5: ./in.cue:2:7 ./in.cue:2:39 ./in.cue:9:8 ./in.cue:9:18 regularFields.err4: invalid value {x:1,y:2} (does not satisfy matchIf): conflicting values 1 and 2: ./in.cue:2:7 ./in.cue:2:39 ./in.cue:10:8 ./in.cue:10:18 Result: (_|_){ // [eval] regularFields: (_|_){ // [eval] ok1: (struct){ x: (int){ 10 } y: (int){ 5 } } ok2: (struct){ x: (int){ 11 } y: (int){ 5 } } ok3: (struct){ x: (int){ 2 } y: (int){ 1 } } ok4: (struct){ x: (int){ 1 } y: (int){ 1 } } err1: (_|_){ // [eval] regularFields.err1: invalid value {x:10,y:6} (does not satisfy matchIf): conflicting values 5 and 6: // ./in.cue:2:7 // ./in.cue:2:30 // ./in.cue:7:8 // ./in.cue:7:19 x: (int){ 10 } y: (int){ 6 } } err2: (_|_){ // [eval] regularFields.err2: invalid value {x:11,y:6} (does not satisfy matchIf): conflicting values 5 and 6: // ./in.cue:2:7 // ./in.cue:2:30 // ./in.cue:8:8 // ./in.cue:8:19 x: (int){ 11 } y: (int){ 6 } } err3: (_|_){ // [eval] regularFields.err3: invalid value {x:2,y:5} (does not satisfy matchIf): conflicting values 1 and 5: // ./in.cue:2:7 // ./in.cue:2:39 // ./in.cue:9:8 // ./in.cue:9:18 x: (int){ 2 } y: (int){ 5 } } err4: (_|_){ // [eval] regularFields.err4: invalid value {x:1,y:2} (does not satisfy matchIf): conflicting values 1 and 2: // ./in.cue:2:7 // ./in.cue:2:39 // ./in.cue:10:8 // ./in.cue:10:18 x: (int){ 1 } y: (int){ 2 } } } } -- out/compile -- --- in.cue { regularFields: { [_]: matchIf({ x!: >2 }, { y!: 5 }, { y!: 1 }) ok1: { x: 10 y: 5 } ok2: { x: 11 y: 5 } ok3: { x: 2 y: 1 } ok4: { x: 1 y: 1 } err1: { x: 10 y: 6 } err2: { x: 11 y: 6 } err3: { x: 2 y: 5 } err4: { x: 1 y: 2 } } } cue-lang-cue-db9cc73/cue/testdata/builtins/matchn.txtar000066400000000000000000001233421474664451600232610ustar00rootroot00000000000000-- in.cue -- import "math" #Foo: { a: int } match: { [=~"^single"]: matchN(1, [#Foo]) singleOK: a: 2 singleErr: a: "foo" [=~"^incomplete"]: matchN(1, [#Foo]) incompleteOK: a: int incompleteErr: a: string #A: { a: int b: _ ... } defaults: { // Because validators distribute over disjunctions, this validator may erase // a default value. Nonethenless, it will be guaranteed that the value // resulting from evaluation does not violate the validator. // TODO(defaults): take this use case into consideration for the defaults // rethink, as it seems less than ideal. Note that this typically not an // issue if the schema matched against is not concrete. [=~"^pickTop"]: matchN(1, [2]) pickTopOK1: *2 | int pickTopOK2: int pickTopErr: *3 | int // Final values taken. // Nested default values will be evaluated and may not be overridden by // values in the validator. [=~"^pickNested1"]: matchN(1, [{a: 2}]) pickNested1OK1: a: *2 | int pickNested1OK2: a: int pickNested1Err: a: *3 | int [=~"^pickNested2"]: matchN(1, [{a: <=2}]) pickNested2OK1: a: *2 | int pickNested2OK2: a: int pickNested2Err: a: *3 | int } // Stress test potential exponential behavior. nestedOK: { matchN(4, [#A, #A, #A, #A]) a: 2 b: { matchN(4, [#A, #A, #A, #A]) a: 3 b: matchN(4, [#A, #A, #A, #A]) b: a: 4 c: matchN(4, [#A, #A, #A, #A]) c: a: 5 } c: { matchN(4, [#A, #A, #A, #A]) a: 3 b: matchN(4, [#A, #A, #A, #A]) b: a: 4 c: matchN(4, [#A, #A, #A, #A]) c: a: 5 } } } not: { [=~"^single"]: matchN(0, [#Foo]) singleOK: a: "foo" singleErr: a: 2 [=~"^double"]: matchN(0, [matchN(0, [#Foo])]) doubleOK: a: 2 doubleErr: a: "foo" } oneOf: { [=~"^multiple1"]: matchN(1, [math.MultipleOf(3), math.MultipleOf(5)]) multiple1Err1: 1 multiple1OK1: 3 multiple1OK2: 5 multiple1Err2: 15 } anyOf: { [=~"^multiple1"]: matchN(>0, [math.MultipleOf(3), math.MultipleOf(5)]) multiple1Err1: 1 multiple1OK1: 3 multiple1OK2: 5 multiple1OK3: 15 } allOf: { [=~"^multiple1"]: matchN(2, [math.MultipleOf(3), math.MultipleOf(5)]) multiple1Err1: 1 multiple1Err2: 3 multiple1Err3: 5 multiple1OK1: 15 } bare: { embed: t1: { a: {matchN(1, [>10])} b: {a} } embed: t2: { b: {a} a: {matchN(1, [>10])} } direct: t1: { a: matchN(1, [>10]) b: a } direct: t2: { b: a a: matchN(1, [>10]) } } required: { ok1: { x: matchN(0, [{foo!: string}]) x: bar: 2 } ok2: { x: matchN(0, [{foo!: string}]) } // not matching for different reasons ok3: { x: matchN(0, [{bar!: string}]) x: bar: 2 } } // A struct with extra fields should match whether or not inside a list. // evalv2 would get this wrong but evalv3 got it right. issue3575: { test1: { #x: matchN(1, [ [{}], ]) x: #x x: [{a: 1}] } test2: { #x: matchN(1, [ {}, ]) x: #x x: {a: 1} } } -- incomplete.cue -- import "math" // The errors in this section should be "incomplete" errors. incomplete: { // foo could still be provided later. incomplete1: { x: matchN(1, [{foo!: string}]) x: bar: 2 } // foo could still be provided later. incomplete2: { x: matchN(1, [{foo!: string}]) } // in case of doubt, we should mark an error as incomplete to be safe. incomplete3: { x: matchN(math.MultipleOf(2), [{bar!: int}, {foo!: int}]) x: bar: 2 } incomplete4: { x: matchN(math.MultipleOf(2), [{bar!: int}, {foo!: int}, {baz!: int}]) x: bar: 2 } incomplete5: { x: matchN(>1 & <=3, [{bar!: int}, {foo!: int}, {baz!: int}]) x: bar: 2 } incomplete6: { x: matchN(2|3, [{bar!: int}, {foo!: int}, {baz!: int}]) x: bar: 2 } // incorrect type cannot be corrected err1: { x: matchN(1, [{bar!: string}]) x: bar: 2 } // additional incomplete matches should not be counted if they can otherwise // not satisfy the constraint. err2: { x: matchN(0, [{bar!: int}, {foo!: int}]) x: bar: 2 } // additional incomplete matches should not be counted if they can otherwise // not satisfy the constraint. err3: { x: matchN(2, [{bar!: string}, {foo!: string}]) x: bar: 2 } // one additional potential match cannot make up to satisfy the bound. err4: { x: matchN(>1, [{bar!: string}, {foo!: string}]) x: bar: 2 } err5: { x: matchN(<1, [{bar!: int}, {foo!: int}]) x: bar: 2 } } -- issue3694.cue -- issue3694: full: { #step: matchN(1, [{ uses!: _ ... }, { run!: _ ... }]) #step: close({ uses?: string run?: string }) s: #step & { run: "echo hello world" } } issue3694: simple: { #step: matchN(1, [{ uses!: _ }]) #step: close({ uses?: string }) } -- out/eval/stats -- Leaks: 19 Freed: 759 Reused: 752 Allocs: 26 Retain: 75 Unifications: 762 Conjuncts: 1269 Disjuncts: 835 -- out/eval -- Errors: match.singleErr: invalid value {a:"foo"} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:8:17 ./in.cue:8:24 ./in.cue:10:13 match.incompleteErr: invalid value {a:string} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:12:21 ./in.cue:12:28 ./in.cue:14:17 match.defaults.pickNested1Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:36:23 ./in.cue:36:30 ./in.cue:39:19 match.defaults.pickNested2Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:41:23 ./in.cue:41:30 ./in.cue:44:19 not.singleErr: invalid value {a:2} (does not satisfy matchN): 1 matched, expected 0: ./in.cue:74:17 ./in.cue:74:24 ./in.cue:76:13 not.doubleErr: invalid value {a:"foo"} (does not satisfy matchN): 1 matched, expected 0: ./in.cue:78:17 ./in.cue:78:24 ./in.cue:80:13 oneOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: ./in.cue:84:20 ./in.cue:84:27 ./in.cue:86:17 oneOf.multiple1Err2: invalid value 15 (does not satisfy matchN): 2 matched, expected 1: ./in.cue:84:20 ./in.cue:84:27 ./in.cue:91:17 anyOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected >0: ./in.cue:95:20 ./in.cue:95:27 ./in.cue:97:17 allOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 2: ./in.cue:106:20 ./in.cue:106:27 ./in.cue:108:17 allOf.multiple1Err2: invalid value 3 (does not satisfy matchN): 1 matched, expected 2: ./in.cue:106:20 ./in.cue:106:27 ./in.cue:109:17 allOf.multiple1Err3: invalid value 5 (does not satisfy matchN): 1 matched, expected 2: ./in.cue:106:20 ./in.cue:106:27 ./in.cue:110:17 issue3575.test1.x: invalid value [{a:1}] (does not satisfy matchN): 0 matched, expected 1: ./in.cue:153:7 ./in.cue:153:14 ./in.cue:156:6 ./in.cue:157:6 incomplete.err1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: ./incomplete.cue:34:6 ./incomplete.cue:34:13 ./incomplete.cue:35:6 incomplete.err2.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected 0: ./incomplete.cue:40:6 ./incomplete.cue:40:13 ./incomplete.cue:41:6 incomplete.err3.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 2: ./incomplete.cue:46:6 ./incomplete.cue:46:13 ./incomplete.cue:47:6 incomplete.err4.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected >1: ./incomplete.cue:51:6 ./incomplete.cue:51:13 ./incomplete.cue:52:6 incomplete.err5.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected <1: ./incomplete.cue:55:6 ./incomplete.cue:55:13 ./incomplete.cue:56:6 Result: (_|_){ // [eval] #Foo: (#struct){ a: (int){ int } } match: (_|_){ // [eval] singleOK: (struct){ a: (int){ 2 } } singleErr: (_|_){ // [eval] match.singleErr: invalid value {a:"foo"} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:8:17 // ./in.cue:8:24 // ./in.cue:10:13 a: (string){ "foo" } } incompleteOK: (struct){ a: (int){ int } } incompleteErr: (_|_){ // [eval] match.incompleteErr: invalid value {a:string} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:12:21 // ./in.cue:12:28 // ./in.cue:14:17 a: (string){ string } } #A: (#struct){ a: (int){ int } b: (_){ _ } } defaults: (_|_){ // [eval] pickTopOK1: (int){ |(*(int){ 2 }, (int){ &(matchN(1, (#list){ 0: (int){ 2 } }), int) }) } pickTopOK2: (int){ &(matchN(1, (#list){ 0: (_|_){// 2 } }), int) } pickTopErr: (int){ &(matchN(1, (#list){ 0: (int){ 2 } }), int) } pickNested1OK1: (struct){ a: (int){ |(*(int){ 2 }, (int){ int }) } } pickNested1OK2: (struct){ a: (int){ int } } pickNested1Err: (_|_){ // [eval] match.defaults.pickNested1Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:36:23 // ./in.cue:36:30 // ./in.cue:39:19 a: (int){ |(*(int){ 3 }, (int){ int }) } } pickNested2OK1: (struct){ a: (int){ |(*(int){ 2 }, (int){ int }) } } pickNested2OK2: (struct){ a: (int){ int } } pickNested2Err: (_|_){ // [eval] match.defaults.pickNested2Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:41:23 // ./in.cue:41:30 // ./in.cue:44:19 a: (int){ |(*(int){ 3 }, (int){ int }) } } } nestedOK: (struct){ a: (int){ 2 } b: (struct){ a: (int){ 3 } b: (struct){ a: (int){ 4 } } c: (struct){ a: (int){ 5 } } } c: (struct){ a: (int){ 3 } b: (struct){ a: (int){ 4 } } c: (struct){ a: (int){ 5 } } } } } not: (_|_){ // [eval] singleOK: (struct){ a: (string){ "foo" } } singleErr: (_|_){ // [eval] not.singleErr: invalid value {a:2} (does not satisfy matchN): 1 matched, expected 0: // ./in.cue:74:17 // ./in.cue:74:24 // ./in.cue:76:13 a: (int){ 2 } } doubleOK: (struct){ a: (int){ 2 } } doubleErr: (_|_){ // [eval] not.doubleErr: invalid value {a:"foo"} (does not satisfy matchN): 1 matched, expected 0: // ./in.cue:78:17 // ./in.cue:78:24 // ./in.cue:80:13 a: (string){ "foo" } } } oneOf: (_|_){ // [eval] multiple1Err1: (_|_){ // [eval] oneOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:84:20 // ./in.cue:84:27 // ./in.cue:86:17 } multiple1OK1: (int){ 3 } multiple1OK2: (int){ 5 } multiple1Err2: (_|_){ // [eval] oneOf.multiple1Err2: invalid value 15 (does not satisfy matchN): 2 matched, expected 1: // ./in.cue:84:20 // ./in.cue:84:27 // ./in.cue:91:17 } } anyOf: (_|_){ // [eval] multiple1Err1: (_|_){ // [eval] anyOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected >0: // ./in.cue:95:20 // ./in.cue:95:27 // ./in.cue:97:17 } multiple1OK1: (int){ 3 } multiple1OK2: (int){ 5 } multiple1OK3: (int){ 15 } } allOf: (_|_){ // [eval] multiple1Err1: (_|_){ // [eval] allOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 2: // ./in.cue:106:20 // ./in.cue:106:27 // ./in.cue:108:17 } multiple1Err2: (_|_){ // [eval] allOf.multiple1Err2: invalid value 3 (does not satisfy matchN): 1 matched, expected 2: // ./in.cue:106:20 // ./in.cue:106:27 // ./in.cue:109:17 } multiple1Err3: (_|_){ // [eval] allOf.multiple1Err3: invalid value 5 (does not satisfy matchN): 1 matched, expected 2: // ./in.cue:106:20 // ./in.cue:106:27 // ./in.cue:110:17 } multiple1OK1: (int){ 15 } } bare: (struct){ embed: (struct){ t1: (struct){ a: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } b: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } } t2: (struct){ b: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } a: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } } } direct: (struct){ t1: (struct){ a: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } b: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } } t2: (struct){ b: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } a: (_){ matchN(1, (#list){ 0: (_|_){// >10 } }) } } } } required: (struct){ ok1: (struct){ x: (struct){ bar: (int){ 2 } } } ok2: (struct){ x: (_){ matchN(0, (#list){ 0: (_|_){// { // foo!: string // } } }) } } ok3: (struct){ x: (struct){ bar: (int){ 2 } } } } issue3575: (_|_){ // [eval] test1: (_|_){ // [eval] #x: (_){ matchN(1, (#list){ 0: (_|_){// [ // {}, // ] } }) } x: (_|_){ // [eval] issue3575.test1.x: invalid value [{a:1}] (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:153:7 // ./in.cue:153:14 // ./in.cue:156:6 // ./in.cue:157:6 0: (struct){ a: (int){ 1 } } } } test2: (struct){ #x: (_){ matchN(1, (#list){ 0: (_|_){// {} } }) } x: (struct){ a: (int){ 1 } } } } incomplete: (_|_){ // [eval] incomplete1: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: // ./incomplete.cue:7:6 // ./incomplete.cue:7:13 // ./incomplete.cue:8:6 bar: (int){ 2 } } } incomplete2: (struct){ x: (_){ matchN(1, (#list){ 0: (_|_){// { // foo!: string // } } }) } } incomplete3: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete3.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected math.MultipleOf(2): // ./incomplete.cue:16:6 // ./incomplete.cue:16:13 // ./incomplete.cue:17:6 bar: (int){ 2 } } } incomplete4: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete4.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected math.MultipleOf(2): // ./incomplete.cue:20:6 // ./incomplete.cue:20:13 // ./incomplete.cue:21:6 bar: (int){ 2 } } } incomplete5: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete5.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected >1 & <=3: // ./incomplete.cue:24:6 // ./incomplete.cue:24:13 // ./incomplete.cue:25:6 bar: (int){ 2 } } } incomplete6: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete6.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected 2 | 3: // ./incomplete.cue:28:6 // ./incomplete.cue:28:13 // ./incomplete.cue:29:6 bar: (int){ 2 } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: // ./incomplete.cue:34:6 // ./incomplete.cue:34:13 // ./incomplete.cue:35:6 bar: (int){ 2 } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err2.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected 0: // ./incomplete.cue:40:6 // ./incomplete.cue:40:13 // ./incomplete.cue:41:6 bar: (int){ 2 } } } err3: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err3.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 2: // ./incomplete.cue:46:6 // ./incomplete.cue:46:13 // ./incomplete.cue:47:6 bar: (int){ 2 } } } err4: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err4.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected >1: // ./incomplete.cue:51:6 // ./incomplete.cue:51:13 // ./incomplete.cue:52:6 bar: (int){ 2 } } } err5: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err5.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected <1: // ./incomplete.cue:55:6 // ./incomplete.cue:55:13 // ./incomplete.cue:56:6 bar: (int){ 2 } } } } issue3694: (struct){ full: (struct){ #step: (_|_){ // [incomplete] issue3694.full.#step: invalid value {uses?:string,run?:string} (does not satisfy matchN): 0 matched, expected 1: // ./issue3694.cue:2:9 // ./issue3694.cue:2:16 // ./issue3694.cue:9:9 uses?: (string){ string } run?: (string){ string } } s: (#struct){ uses?: (string){ string } run: (string){ "echo hello world" } } } simple: (struct){ #step: (_|_){ // [incomplete] issue3694.simple.#step: invalid value {uses?:string} (does not satisfy matchN): 0 matched, expected 1: // ./issue3694.cue:19:9 // ./issue3694.cue:19:16 // ./issue3694.cue:22:9 uses?: (string){ string } } } } } -- out/evalalpha -- Errors: match.singleErr: invalid value {a:"foo"} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:8:17 ./in.cue:8:24 ./in.cue:10:13 match.incompleteErr: invalid value {a:string} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:12:21 ./in.cue:12:28 ./in.cue:14:17 match.defaults.pickNested1Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:36:23 ./in.cue:36:30 ./in.cue:39:19 match.defaults.pickNested2Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: ./in.cue:41:23 ./in.cue:41:30 ./in.cue:44:19 not.singleErr: invalid value {a:2} (does not satisfy matchN): 1 matched, expected 0: ./in.cue:74:17 ./in.cue:74:24 ./in.cue:76:13 not.doubleErr: invalid value {a:"foo"} (does not satisfy matchN): 1 matched, expected 0: ./in.cue:78:17 ./in.cue:78:24 ./in.cue:80:13 oneOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: ./in.cue:84:20 ./in.cue:84:27 ./in.cue:86:17 oneOf.multiple1Err2: invalid value 15 (does not satisfy matchN): 2 matched, expected 1: ./in.cue:84:20 ./in.cue:84:27 ./in.cue:91:17 anyOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected >0: ./in.cue:95:20 ./in.cue:95:27 ./in.cue:97:17 allOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 2: ./in.cue:106:20 ./in.cue:106:27 ./in.cue:108:17 allOf.multiple1Err2: invalid value 3 (does not satisfy matchN): 1 matched, expected 2: ./in.cue:106:20 ./in.cue:106:27 ./in.cue:109:17 allOf.multiple1Err3: invalid value 5 (does not satisfy matchN): 1 matched, expected 2: ./in.cue:106:20 ./in.cue:106:27 ./in.cue:110:17 incomplete.err1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: ./incomplete.cue:34:6 ./incomplete.cue:34:13 ./incomplete.cue:35:6 incomplete.err2.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected 0: ./incomplete.cue:40:6 ./incomplete.cue:40:13 ./incomplete.cue:41:6 incomplete.err3.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 2: ./incomplete.cue:46:6 ./incomplete.cue:46:13 ./incomplete.cue:47:6 incomplete.err4.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected >1: ./incomplete.cue:51:6 ./incomplete.cue:51:13 ./incomplete.cue:52:6 incomplete.err5.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected <1: ./incomplete.cue:55:6 ./incomplete.cue:55:13 ./incomplete.cue:56:6 Result: (_|_){ // [eval] #Foo: (#struct){ a: (int){ int } } match: (_|_){ // [eval] singleOK: (struct){ a: (int){ 2 } } singleErr: (_|_){ // [eval] match.singleErr: invalid value {a:"foo"} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:8:17 // ./in.cue:8:24 // ./in.cue:10:13 a: (string){ "foo" } } incompleteOK: (struct){ a: (int){ int } } incompleteErr: (_|_){ // [eval] match.incompleteErr: invalid value {a:string} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:12:21 // ./in.cue:12:28 // ./in.cue:14:17 a: (string){ string } } #A: (#struct){ a: (int){ int } b: (_){ _ } } defaults: (_|_){ // [eval] pickTopOK1: (int){ |(*(int){ 2 }, (int){ &(matchN(1, (#list){ 0: (int){ 2 } }), int) }) } pickTopOK2: (int){ &(matchN(1, (#list){ 0: (_|_){// &[2] } }), int) } pickTopErr: (int){ &(matchN(1, (#list){ 0: (int){ 2 } }), int) } pickNested1OK1: (struct){ a: (int){ |(*(int){ 2 }, (int){ int }) } } pickNested1OK2: (struct){ a: (int){ int } } pickNested1Err: (_|_){ // [eval] match.defaults.pickNested1Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:36:23 // ./in.cue:36:30 // ./in.cue:39:19 a: (int){ |(*(int){ 3 }, (int){ int }) } } pickNested2OK1: (struct){ a: (int){ |(*(int){ 2 }, (int){ int }) } } pickNested2OK2: (struct){ a: (int){ int } } pickNested2Err: (_|_){ // [eval] match.defaults.pickNested2Err: invalid value {a:*3 | int} (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:41:23 // ./in.cue:41:30 // ./in.cue:44:19 a: (int){ |(*(int){ 3 }, (int){ int }) } } } nestedOK: (struct){ a: (int){ 2 } b: (struct){ a: (int){ 3 } b: (struct){ a: (int){ 4 } } c: (struct){ a: (int){ 5 } } } c: (struct){ a: (int){ 3 } b: (struct){ a: (int){ 4 } } c: (struct){ a: (int){ 5 } } } } } not: (_|_){ // [eval] singleOK: (struct){ a: (string){ "foo" } } singleErr: (_|_){ // [eval] not.singleErr: invalid value {a:2} (does not satisfy matchN): 1 matched, expected 0: // ./in.cue:74:17 // ./in.cue:74:24 // ./in.cue:76:13 a: (int){ 2 } } doubleOK: (struct){ a: (int){ 2 } } doubleErr: (_|_){ // [eval] not.doubleErr: invalid value {a:"foo"} (does not satisfy matchN): 1 matched, expected 0: // ./in.cue:78:17 // ./in.cue:78:24 // ./in.cue:80:13 a: (string){ "foo" } } } oneOf: (_|_){ // [eval] multiple1Err1: (_|_){ // [eval] oneOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: // ./in.cue:84:20 // ./in.cue:84:27 // ./in.cue:86:17 } multiple1OK1: (int){ 3 } multiple1OK2: (int){ 5 } multiple1Err2: (_|_){ // [eval] oneOf.multiple1Err2: invalid value 15 (does not satisfy matchN): 2 matched, expected 1: // ./in.cue:84:20 // ./in.cue:84:27 // ./in.cue:91:17 } } anyOf: (_|_){ // [eval] multiple1Err1: (_|_){ // [eval] anyOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected >0: // ./in.cue:95:20 // ./in.cue:95:27 // ./in.cue:97:17 } multiple1OK1: (int){ 3 } multiple1OK2: (int){ 5 } multiple1OK3: (int){ 15 } } allOf: (_|_){ // [eval] multiple1Err1: (_|_){ // [eval] allOf.multiple1Err1: invalid value 1 (does not satisfy matchN): 0 matched, expected 2: // ./in.cue:106:20 // ./in.cue:106:27 // ./in.cue:108:17 } multiple1Err2: (_|_){ // [eval] allOf.multiple1Err2: invalid value 3 (does not satisfy matchN): 1 matched, expected 2: // ./in.cue:106:20 // ./in.cue:106:27 // ./in.cue:109:17 } multiple1Err3: (_|_){ // [eval] allOf.multiple1Err3: invalid value 5 (does not satisfy matchN): 1 matched, expected 2: // ./in.cue:106:20 // ./in.cue:106:27 // ./in.cue:110:17 } multiple1OK1: (int){ 15 } } bare: (struct){ embed: (struct){ t1: (struct){ a: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } b: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } } t2: (struct){ b: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } a: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } } } direct: (struct){ t1: (struct){ a: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } b: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } } t2: (struct){ b: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } a: (_){ matchN(1, (#list){ 0: (_|_){// &[>10] } }) } } } } required: (struct){ ok1: (struct){ x: (struct){ bar: (int){ 2 } } } ok2: (struct){ x: (_){ matchN(0, (#list){ 0: (_|_){// &[{ // foo!: string // }] } }) } } ok3: (struct){ x: (struct){ bar: (int){ 2 } } } } issue3575: (struct){ test1: (struct){ #x: (_){ matchN(1, (#list){ 0: (_|_){// &[[ // {}, // ]] } }) } x: (#list){ 0: (#struct){ a: (int){ 1 } } } } test2: (struct){ #x: (_){ matchN(1, (#list){ 0: (_|_){// &[{}] } }) } x: (#struct){ a: (int){ 1 } } } } incomplete: (_|_){ // [eval] incomplete1: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: // ./incomplete.cue:7:6 // ./incomplete.cue:7:13 // ./incomplete.cue:8:6 bar: (int){ 2 } } } incomplete2: (struct){ x: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // foo!: string // }] } }) } } incomplete3: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete3.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected math.MultipleOf(2): // ./incomplete.cue:16:6 // ./incomplete.cue:16:13 // ./incomplete.cue:17:6 bar: (int){ 2 } } } incomplete4: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete4.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected math.MultipleOf(2): // ./incomplete.cue:20:6 // ./incomplete.cue:20:13 // ./incomplete.cue:21:6 bar: (int){ 2 } } } incomplete5: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete5.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected >1 & <=3: // ./incomplete.cue:24:6 // ./incomplete.cue:24:13 // ./incomplete.cue:25:6 bar: (int){ 2 } } } incomplete6: (struct){ x: (_|_){ // [incomplete] incomplete.incomplete6.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected 2 | 3: // ./incomplete.cue:28:6 // ./incomplete.cue:28:13 // ./incomplete.cue:29:6 bar: (int){ 2 } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: // ./incomplete.cue:34:6 // ./incomplete.cue:34:13 // ./incomplete.cue:35:6 bar: (int){ 2 } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err2.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected 0: // ./incomplete.cue:40:6 // ./incomplete.cue:40:13 // ./incomplete.cue:41:6 bar: (int){ 2 } } } err3: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err3.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 2: // ./incomplete.cue:46:6 // ./incomplete.cue:46:13 // ./incomplete.cue:47:6 bar: (int){ 2 } } } err4: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err4.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected >1: // ./incomplete.cue:51:6 // ./incomplete.cue:51:13 // ./incomplete.cue:52:6 bar: (int){ 2 } } } err5: (_|_){ // [eval] x: (_|_){ // [eval] incomplete.err5.x: invalid value {bar:2} (does not satisfy matchN): 1 matched, expected <1: // ./incomplete.cue:55:6 // ./incomplete.cue:55:13 // ./incomplete.cue:56:6 bar: (int){ 2 } } } } issue3694: (struct){ full: (struct){ #step: (_|_){ // [incomplete] issue3694.full.#step: invalid value {uses?:string,run?:string} (does not satisfy matchN): 0 matched, expected 1: // ./issue3694.cue:2:9 // ./issue3694.cue:2:16 // ./issue3694.cue:9:9 uses?: (string){ string } run?: (string){ string } } s: (#struct){ run: (string){ "echo hello world" } uses?: (string){ string } } } simple: (struct){ #step: (_|_){ // [incomplete] issue3694.simple.#step: invalid value {uses?:string} (does not satisfy matchN): 0 matched, expected 1: // ./issue3694.cue:19:9 // ./issue3694.cue:19:16 // ./issue3694.cue:22:9 uses?: (string){ string } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -47,11 +47,6 @@ ./in.cue:106:20 ./in.cue:106:27 ./in.cue:110:17 -issue3575.test1.x: invalid value [{a:1}] (does not satisfy matchN): 0 matched, expected 1: - ./in.cue:153:7 - ./in.cue:153:14 - ./in.cue:156:6 - ./in.cue:157:6 incomplete.err1.x: invalid value {bar:2} (does not satisfy matchN): 0 matched, expected 1: ./incomplete.cue:34:6 ./incomplete.cue:34:13 @@ -111,7 +106,7 @@ 0: (int){ 2 } }), int) }) } pickTopOK2: (int){ &(matchN(1, (#list){ - 0: (_|_){// 2 + 0: (_|_){// &[2] } }), int) } pickTopErr: (int){ &(matchN(1, (#list){ @@ -244,21 +239,21 @@ embed: (struct){ t1: (struct){ a: (_){ matchN(1, (#list){ - 0: (_|_){// >10 - } - }) } - b: (_){ matchN(1, (#list){ - 0: (_|_){// >10 - } - }) } - } - t2: (struct){ - b: (_){ matchN(1, (#list){ - 0: (_|_){// >10 - } - }) } - a: (_){ matchN(1, (#list){ - 0: (_|_){// >10 + 0: (_|_){// &[>10] + } + }) } + b: (_){ matchN(1, (#list){ + 0: (_|_){// &[>10] + } + }) } + } + t2: (struct){ + b: (_){ matchN(1, (#list){ + 0: (_|_){// &[>10] + } + }) } + a: (_){ matchN(1, (#list){ + 0: (_|_){// &[>10] } }) } } @@ -266,21 +261,21 @@ direct: (struct){ t1: (struct){ a: (_){ matchN(1, (#list){ - 0: (_|_){// >10 - } - }) } - b: (_){ matchN(1, (#list){ - 0: (_|_){// >10 - } - }) } - } - t2: (struct){ - b: (_){ matchN(1, (#list){ - 0: (_|_){// >10 - } - }) } - a: (_){ matchN(1, (#list){ - 0: (_|_){// >10 + 0: (_|_){// &[>10] + } + }) } + b: (_){ matchN(1, (#list){ + 0: (_|_){// &[>10] + } + }) } + } + t2: (struct){ + b: (_){ matchN(1, (#list){ + 0: (_|_){// &[>10] + } + }) } + a: (_){ matchN(1, (#list){ + 0: (_|_){// &[>10] } }) } } @@ -294,9 +289,9 @@ } ok2: (struct){ x: (_){ matchN(0, (#list){ - 0: (_|_){// { - // foo!: string - // } + 0: (_|_){// &[{ + // foo!: string + // }] } }) } } @@ -306,23 +301,16 @@ } } } - issue3575: (_|_){ - // [eval] - test1: (_|_){ - // [eval] - #x: (_){ matchN(1, (#list){ - 0: (_|_){// [ + issue3575: (struct){ + test1: (struct){ + #x: (_){ matchN(1, (#list){ + 0: (_|_){// &[[ // {}, - // ] - } - }) } - x: (_|_){ - // [eval] issue3575.test1.x: invalid value [{a:1}] (does not satisfy matchN): 0 matched, expected 1: - // ./in.cue:153:7 - // ./in.cue:153:14 - // ./in.cue:156:6 - // ./in.cue:157:6 - 0: (struct){ + // ]] + } + }) } + x: (#list){ + 0: (#struct){ a: (int){ 1 } } } @@ -329,10 +317,10 @@ } test2: (struct){ #x: (_){ matchN(1, (#list){ - 0: (_|_){// {} - } - }) } - x: (struct){ + 0: (_|_){// &[{}] + } + }) } + x: (#struct){ a: (int){ 1 } } } @@ -350,9 +338,9 @@ } incomplete2: (struct){ x: (_){ matchN(1, (#list){ - 0: (_|_){// { - // foo!: string - // } + 0: (_|_){// &[{ + // foo!: string + // }] } }) } } @@ -454,8 +442,8 @@ run?: (string){ string } } s: (#struct){ - uses?: (string){ string } run: (string){ "echo hello world" } + uses?: (string){ string } } } simple: (struct){ -- diff/explanation -- The old evaluator does not correctly handle ToDataAll if a node is mid-evaluation. The new evaluator does. issue3575: the old evaluator was incorrect in behaving differently when using structs inside lists -- diff/todo/p3 -- Missing error positions. -- out/compile -- --- in.cue { #Foo: { a: int } match: { [=~"^single"]: matchN(1, [ 〈2;#Foo〉, ]) singleOK: { a: 2 } singleErr: { a: "foo" } [=~"^incomplete"]: matchN(1, [ 〈2;#Foo〉, ]) incompleteOK: { a: int } incompleteErr: { a: string } #A: { a: int b: _ ... } defaults: { [=~"^pickTop"]: matchN(1, [ 2, ]) pickTopOK1: (*2|int) pickTopOK2: int pickTopErr: (*3|int) [=~"^pickNested1"]: matchN(1, [ { a: 2 }, ]) pickNested1OK1: { a: (*2|int) } pickNested1OK2: { a: int } pickNested1Err: { a: (*3|int) } [=~"^pickNested2"]: matchN(1, [ { a: <=2 }, ]) pickNested2OK1: { a: (*2|int) } pickNested2OK2: { a: int } pickNested2Err: { a: (*3|int) } } nestedOK: { matchN(4, [ 〈2;#A〉, 〈2;#A〉, 〈2;#A〉, 〈2;#A〉, ]) a: 2 b: { matchN(4, [ 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, ]) a: 3 b: matchN(4, [ 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, ]) b: { a: 4 } c: matchN(4, [ 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, ]) c: { a: 5 } } c: { matchN(4, [ 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, ]) a: 3 b: matchN(4, [ 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, ]) b: { a: 4 } c: matchN(4, [ 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, 〈3;#A〉, ]) c: { a: 5 } } } } not: { [=~"^single"]: matchN(0, [ 〈2;#Foo〉, ]) singleOK: { a: "foo" } singleErr: { a: 2 } [=~"^double"]: matchN(0, [ matchN(0, [ 〈3;#Foo〉, ]), ]) doubleOK: { a: 2 } doubleErr: { a: "foo" } } oneOf: { [=~"^multiple1"]: matchN(1, [ 〈import;math〉.MultipleOf(3), 〈import;math〉.MultipleOf(5), ]) multiple1Err1: 1 multiple1OK1: 3 multiple1OK2: 5 multiple1Err2: 15 } anyOf: { [=~"^multiple1"]: matchN(>0, [ 〈import;math〉.MultipleOf(3), 〈import;math〉.MultipleOf(5), ]) multiple1Err1: 1 multiple1OK1: 3 multiple1OK2: 5 multiple1OK3: 15 } allOf: { [=~"^multiple1"]: matchN(2, [ 〈import;math〉.MultipleOf(3), 〈import;math〉.MultipleOf(5), ]) multiple1Err1: 1 multiple1Err2: 3 multiple1Err3: 5 multiple1OK1: 15 } bare: { embed: { t1: { a: { matchN(1, [ >10, ]) } b: { 〈1;a〉 } } } embed: { t2: { b: { 〈1;a〉 } a: { matchN(1, [ >10, ]) } } } direct: { t1: { a: matchN(1, [ >10, ]) b: 〈0;a〉 } } direct: { t2: { b: 〈0;a〉 a: matchN(1, [ >10, ]) } } } required: { ok1: { x: matchN(0, [ { foo!: string }, ]) x: { bar: 2 } } ok2: { x: matchN(0, [ { foo!: string }, ]) } ok3: { x: matchN(0, [ { bar!: string }, ]) x: { bar: 2 } } } issue3575: { test1: { #x: matchN(1, [ [ {}, ], ]) x: 〈0;#x〉 x: [ { a: 1 }, ] } test2: { #x: matchN(1, [ {}, ]) x: 〈0;#x〉 x: { a: 1 } } } } --- incomplete.cue { incomplete: { incomplete1: { x: matchN(1, [ { foo!: string }, ]) x: { bar: 2 } } incomplete2: { x: matchN(1, [ { foo!: string }, ]) } incomplete3: { x: matchN(〈import;math〉.MultipleOf(2), [ { bar!: int }, { foo!: int }, ]) x: { bar: 2 } } incomplete4: { x: matchN(〈import;math〉.MultipleOf(2), [ { bar!: int }, { foo!: int }, { baz!: int }, ]) x: { bar: 2 } } incomplete5: { x: matchN((>1 & <=3), [ { bar!: int }, { foo!: int }, { baz!: int }, ]) x: { bar: 2 } } incomplete6: { x: matchN((2|3), [ { bar!: int }, { foo!: int }, { baz!: int }, ]) x: { bar: 2 } } err1: { x: matchN(1, [ { bar!: string }, ]) x: { bar: 2 } } err2: { x: matchN(0, [ { bar!: int }, { foo!: int }, ]) x: { bar: 2 } } err3: { x: matchN(2, [ { bar!: string }, { foo!: string }, ]) x: { bar: 2 } } err4: { x: matchN(>1, [ { bar!: string }, { foo!: string }, ]) x: { bar: 2 } } err5: { x: matchN(<1, [ { bar!: int }, { foo!: int }, ]) x: { bar: 2 } } } } --- issue3694.cue { issue3694: { full: { #step: matchN(1, [ { uses!: _ ... }, { run!: _ ... }, ]) #step: close({ uses?: string run?: string }) s: (〈0;#step〉 & { run: "echo hello world" }) } } issue3694: { simple: { #step: matchN(1, [ { uses!: _ }, ]) #step: close({ uses?: string }) } } } cue-lang-cue-db9cc73/cue/testdata/builtins/or.txtar000066400000000000000000000004041474664451600224200ustar00rootroot00000000000000// unwrap into single value unwrap: or([1, 1, 1]) // unique duplicate values unique1: or([2, 1, 1, 2]) unique2: or([{a: 1}, {a: 1}, {a: 2}]) // do not unique embedded scalars with differing values for child definitions. embed1: or([{2, #x: 1}, {2, #x: 2}]) cue-lang-cue-db9cc73/cue/testdata/builtins/validators.txtar000066400000000000000000000671441474664451600241660ustar00rootroot00000000000000-- in.cue -- import ( "encoding/json" "list" "struct" ) // non-monotonic builtins must fail with an "incomplete" error if there // is a possibility the constraint can get resolved by becoming more specific. incompleteError1: { MyType: { kv: struct.MinFields(1) } foo: MyType & { kv: joel: "testing" } } incompleteError2: { MyType: { kv: [string]: string kv: struct.MinFields(1) } foo: MyType & { kv: joel: "testing" } } incompleteError3: { t: string t: json.Validate(string) } uniqueConstrains1: { t: string t: json.Validate(string) t: json.Validate(string) } uniqueConstrains2: { t: struct.MaxFields(1) t: struct.MaxFields(1) } violation: { #MyType: { kv: [string]: string kv: struct.MinFields(1) } foo: #MyType & { kv: joel: "testing" kv: tony: "testing" } } conjuncts: { kv: struct.MinFields(1) kv: struct.MaxFields(3) } // TODO: stripe off conflicting pairs // conflicting: { // kv: struct.MinFields(3) // kv: struct.MaxFields(1) // } // Builtins with bool return that can be used as validator. bareBuiltin: { a: json.Valid a: json.Valid } bareBuiltinCheck: { a: json.Valid a: "3" } builtinValidator: { a: json.Valid() a: json.Valid() } builtinValidatorCheck: { a: json.Valid() a: "3" } callOfCallToValidator: { a: json.Valid b: a() e: b() // not allowed e: "5" } validatorAsFunction: { a: json.Valid b: a("3") c: json.Valid("3") } issue2098: ok1: { _a: [1, ...] _a: list.MinItems(1) _a[0] } issue2098: incomplete1: { _a: [...] _a: list.MinItems(1) _a[0] } -- issue3418.cue -- issue3418: t1: "foo" & matchN(1, [1&2]) & matchN(1, [_]) issue3418: t2: "foo" & matchN(1, [_]) & matchN(1, [1&2]) issue3418: t3: { x: "foo" x: matchN(1, [_]) x: matchN(1, [1&2]) } issue3418: t4: { x: "foo" x: matchN(1, [1&2]) x: matchN(1, [_]) } -- issue3474.cue -- import "struct" issue3474: structValidator: ok: { // Passes only after the comprehension is evaluated. A: struct.MinFields(1) A: { if true {B: true} } } issue3474: structValidator: failAfter: { // Passes only before the comprehension is evaluated. A: struct.MaxFields(1) A: { C: true if true {B: true} } } issue3474: structValidator: incomplete: { // Passes neither before nor after the comprehension is evaluated. A: struct.MinFields(1) A: { if true {} } } issue3474: structValidator: failClosed: { // Passes neither before nor after the comprehension is evaluated. #A: struct.MinFields(1) #A: { if true {} } } issue3474: topValidator: ok: { A: matchN(1, [>10]) A: { if true {100} } } issue3474: topValidator: fail: { A: matchN(1, [>10]) A: { if true {1} } } issue3474: topValidator: incomplete: { A: matchN(1, [>10]) A: { if true {int} } } issue3474: topValidator: failType: { A: matchN(1, [>10]) A: { if true {C: 1} } } -- validator_is_top.cue -- issue3639: { a: {#X} & #X a: b: 1 #X: matchN(1, [{b: int}]) } issue3661: { #X: matchN(1, [{ b!: int }]) a: b: 1 a: #X ["a"]: #X } issue3678: { #X: matchN(1, [{ a!: string }, { c!: string }]) x: c: "c" y: #X y: x x: #X } -- out/eval/stats -- Leaks: 4 Freed: 177 Reused: 170 Allocs: 11 Retain: 23 Unifications: 181 Conjuncts: 327 Disjuncts: 202 -- out/evalalpha -- Errors: callOfCallToValidator.e: cannot call previously called validator b: ./in.cue:94:5 issue3418.t1: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:1:24 ./issue3418.cue:1:16 ./issue3418.cue:1:31 ./issue3418.cue:1:35 ./issue3418.cue:1:37 issue3418.t2: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:2:41 ./issue3418.cue:2:16 ./issue3418.cue:2:48 ./issue3418.cue:2:52 ./issue3418.cue:2:54 issue3418.t3.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:6:5 ./issue3418.cue:4:5 ./issue3418.cue:5:5 ./issue3418.cue:6:12 ./issue3418.cue:6:16 ./issue3418.cue:6:18 issue3418.t4.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:10:5 ./issue3418.cue:9:5 ./issue3418.cue:10:12 ./issue3418.cue:10:16 ./issue3418.cue:10:18 ./issue3418.cue:11:5 issue3474.structValidator.failAfter.A: invalid value {C:true,B:true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): ./issue3474.cue:12:5 ./issue3474.cue:12:22 ./issue3474.cue:13:5 issue3474.structValidator.failClosed.#A: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): ./issue3474.cue:27:6 ./issue3474.cue:27:23 ./issue3474.cue:28:6 issue3474.topValidator.fail.A: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: ./issue3474.cue:41:5 ./issue3474.cue:41:12 ./issue3474.cue:42:5 ./issue3474.cue:43:12 issue3474.topValidator.failType.A: invalid value {C:1} (does not satisfy matchN): 0 matched, expected 1: ./issue3474.cue:53:5 ./issue3474.cue:53:12 ./issue3474.cue:54:5 Result: (_|_){ // [eval] incompleteError1: (struct){ MyType: (struct){ kv: (struct){ struct.MinFields(1) } } foo: (struct){ kv: (struct){ joel: (string){ "testing" } } } } incompleteError2: (struct){ MyType: (struct){ kv: (_|_){ // [incomplete] incompleteError2.MyType.kv: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./in.cue:22:7 // ./in.cue:21:7 // ./in.cue:22:24 } } foo: (struct){ kv: (struct){ joel: (string){ "testing" } } } } incompleteError3: (struct){ t: (string){ &("encoding/json".Validate(string), string) } } uniqueConstrains1: (struct){ t: (string){ &("encoding/json".Validate(string), string) } } uniqueConstrains2: (struct){ t: (struct){ struct.MaxFields(1) } } violation: (struct){ #MyType: (#struct){ kv: (_|_){ // [incomplete] violation.#MyType.kv: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./in.cue:49:7 // ./in.cue:48:7 // ./in.cue:49:24 } } foo: (#struct){ kv: (#struct){ joel: (string){ "testing" } tony: (string){ "testing" } } } } conjuncts: (struct){ kv: (struct){ &(struct.MinFields(1), struct.MaxFields(3)) } } bareBuiltin: (struct){ a: ((string|bytes)){ "encoding/json".Valid() } } bareBuiltinCheck: (struct){ a: (string){ "3" } } builtinValidator: (struct){ a: ((string|bytes)){ "encoding/json".Valid() } } builtinValidatorCheck: (struct){ a: (string){ "3" } } callOfCallToValidator: (_|_){ // [eval] a: ((string|bytes)){ "encoding/json".Valid() } b: ((string|bytes)){ "encoding/json".Valid() } e: (_|_){ // [eval] callOfCallToValidator.e: cannot call previously called validator b: // ./in.cue:94:5 } } validatorAsFunction: (struct){ a: ((string|bytes)){ "encoding/json".Valid() } b: (bool){ true } c: (bool){ true } } issue2098: (struct){ ok1: (int){ 1 _a: (list){ 0: (int){ 1 } } } incomplete1: (struct){ _a: (_|_){ // [incomplete] issue2098.incomplete1._a: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1): // ./in.cue:112:6 // ./in.cue:111:6 // ./in.cue:112:20 } } } issue3418: (_|_){ // [eval] t1: (_|_){ // [eval] issue3418.t1: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:1:24 // ./issue3418.cue:1:16 // ./issue3418.cue:1:31 // ./issue3418.cue:1:35 // ./issue3418.cue:1:37 } t2: (_|_){ // [eval] issue3418.t2: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:2:41 // ./issue3418.cue:2:16 // ./issue3418.cue:2:48 // ./issue3418.cue:2:52 // ./issue3418.cue:2:54 } t3: (_|_){ // [eval] x: (_|_){ // [eval] issue3418.t3.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:6:5 // ./issue3418.cue:4:5 // ./issue3418.cue:5:5 // ./issue3418.cue:6:12 // ./issue3418.cue:6:16 // ./issue3418.cue:6:18 } } t4: (_|_){ // [eval] x: (_|_){ // [eval] issue3418.t4.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:10:5 // ./issue3418.cue:9:5 // ./issue3418.cue:10:12 // ./issue3418.cue:10:16 // ./issue3418.cue:10:18 // ./issue3418.cue:11:5 } } } issue3474: (_|_){ // [eval] structValidator: (_|_){ // [eval] ok: (struct){ A: (struct){ B: (bool){ true } } } failAfter: (_|_){ // [eval] A: (_|_){ // [eval] issue3474.structValidator.failAfter.A: invalid value {C:true,B:true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): // ./issue3474.cue:12:5 // ./issue3474.cue:12:22 // ./issue3474.cue:13:5 C: (bool){ true } B: (bool){ true } } } incomplete: (struct){ A: (_|_){ // [incomplete] issue3474.structValidator.incomplete.A: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./issue3474.cue:20:5 // ./issue3474.cue:20:22 // ./issue3474.cue:21:5 } } failClosed: (_|_){ // [eval] #A: (_|_){ // [eval] issue3474.structValidator.failClosed.#A: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./issue3474.cue:27:6 // ./issue3474.cue:27:23 // ./issue3474.cue:28:6 } } } topValidator: (_|_){ // [eval] ok: (struct){ A: (int){ 100 } } fail: (_|_){ // [eval] A: (_|_){ // [eval] issue3474.topValidator.fail.A: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: // ./issue3474.cue:41:5 // ./issue3474.cue:41:12 // ./issue3474.cue:42:5 // ./issue3474.cue:43:12 } } incomplete: (struct){ A: (int){ &(matchN(1, (#list){ 0: (_|_){// &[>10] } }), int) } } failType: (_|_){ // [eval] A: (_|_){ // [eval] issue3474.topValidator.failType.A: invalid value {C:1} (does not satisfy matchN): 0 matched, expected 1: // ./issue3474.cue:53:5 // ./issue3474.cue:53:12 // ./issue3474.cue:54:5 C: (int){ 1 } } } } } issue3639: (struct){ a: (#struct){ b: (int){ 1 } } #X: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // b: int // }] } }) } } issue3661: (struct){ #X: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // b!: int // }] } }) } a: (#struct){ b: (int){ 1 } } } issue3678: (struct){ #X: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // a!: string // }] } 1: (_|_){// &[{ // c!: string // }] } }) } x: (#struct){ c: (string){ "c" } } y: (#struct){ c: (string){ "c" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -27,7 +27,7 @@ ./issue3418.cue:10:16 ./issue3418.cue:10:18 ./issue3418.cue:11:5 -issue3474.structValidator.failAfter.A: invalid value {C:true,B*:if true true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): +issue3474.structValidator.failAfter.A: invalid value {C:true,B:true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): ./issue3474.cue:12:5 ./issue3474.cue:12:22 ./issue3474.cue:13:5 @@ -134,11 +134,7 @@ 0: (int){ 1 } } } - incomplete1: (_|_){ - // [incomplete] issue2098.incomplete1._a: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1): - // ./in.cue:112:6 - // ./in.cue:111:6 - // ./in.cue:112:20 + incomplete1: (struct){ _a: (_|_){ // [incomplete] issue2098.incomplete1._a: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1): // ./in.cue:112:6 @@ -202,7 +198,7 @@ failAfter: (_|_){ // [eval] A: (_|_){ - // [eval] issue3474.structValidator.failAfter.A: invalid value {C:true,B*:if true true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): + // [eval] issue3474.structValidator.failAfter.A: invalid value {C:true,B:true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): // ./issue3474.cue:12:5 // ./issue3474.cue:12:22 // ./issue3474.cue:13:5 @@ -245,7 +241,7 @@ } incomplete: (struct){ A: (int){ &(matchN(1, (#list){ - 0: (_|_){// >10 + 0: (_|_){// &[>10] } }), int) } } @@ -262,42 +258,42 @@ } } issue3639: (struct){ - a: (struct){ - b: (int){ 1 } - } - #X: (_){ matchN(1, (#list){ - 0: (_|_){// { + a: (#struct){ + b: (int){ 1 } + } + #X: (_){ matchN(1, (#list){ + 0: (_|_){// &[{ // b: int - // } + // }] } }) } } issue3661: (struct){ #X: (_){ matchN(1, (#list){ - 0: (_|_){// { + 0: (_|_){// &[{ // b!: int - // } - } - }) } - a: (struct){ + // }] + } + }) } + a: (#struct){ b: (int){ 1 } } } issue3678: (struct){ #X: (_){ matchN(1, (#list){ - 0: (_|_){// { + 0: (_|_){// &[{ // a!: string - // } - } - 1: (_|_){// { + // }] + } + 1: (_|_){// &[{ // c!: string - // } - } - }) } - x: (struct){ - c: (string){ "c" } - } - y: (struct){ + // }] + } + }) } + x: (#struct){ + c: (string){ "c" } + } + y: (#struct){ c: (string){ "c" } } } -- out/eval -- Errors: callOfCallToValidator.e: cannot call previously called validator b: ./in.cue:94:5 issue3418.t1: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:1:24 ./issue3418.cue:1:16 ./issue3418.cue:1:31 ./issue3418.cue:1:35 ./issue3418.cue:1:37 issue3418.t2: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:2:41 ./issue3418.cue:2:16 ./issue3418.cue:2:48 ./issue3418.cue:2:52 ./issue3418.cue:2:54 issue3418.t3.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:6:5 ./issue3418.cue:4:5 ./issue3418.cue:5:5 ./issue3418.cue:6:12 ./issue3418.cue:6:16 ./issue3418.cue:6:18 issue3418.t4.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: ./issue3418.cue:10:5 ./issue3418.cue:9:5 ./issue3418.cue:10:12 ./issue3418.cue:10:16 ./issue3418.cue:10:18 ./issue3418.cue:11:5 issue3474.structValidator.failAfter.A: invalid value {C:true,B*:if true true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): ./issue3474.cue:12:5 ./issue3474.cue:12:22 ./issue3474.cue:13:5 issue3474.structValidator.failClosed.#A: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): ./issue3474.cue:27:6 ./issue3474.cue:27:23 ./issue3474.cue:28:6 issue3474.topValidator.fail.A: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: ./issue3474.cue:41:5 ./issue3474.cue:41:12 ./issue3474.cue:42:5 ./issue3474.cue:43:12 issue3474.topValidator.failType.A: invalid value {C:1} (does not satisfy matchN): 0 matched, expected 1: ./issue3474.cue:53:5 ./issue3474.cue:53:12 ./issue3474.cue:54:5 Result: (_|_){ // [eval] incompleteError1: (struct){ MyType: (struct){ kv: (struct){ struct.MinFields(1) } } foo: (struct){ kv: (struct){ joel: (string){ "testing" } } } } incompleteError2: (struct){ MyType: (struct){ kv: (_|_){ // [incomplete] incompleteError2.MyType.kv: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./in.cue:22:7 // ./in.cue:21:7 // ./in.cue:22:24 } } foo: (struct){ kv: (struct){ joel: (string){ "testing" } } } } incompleteError3: (struct){ t: (string){ &("encoding/json".Validate(string), string) } } uniqueConstrains1: (struct){ t: (string){ &("encoding/json".Validate(string), string) } } uniqueConstrains2: (struct){ t: (struct){ struct.MaxFields(1) } } violation: (struct){ #MyType: (#struct){ kv: (_|_){ // [incomplete] violation.#MyType.kv: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./in.cue:49:7 // ./in.cue:48:7 // ./in.cue:49:24 } } foo: (#struct){ kv: (#struct){ joel: (string){ "testing" } tony: (string){ "testing" } } } } conjuncts: (struct){ kv: (struct){ &(struct.MinFields(1), struct.MaxFields(3)) } } bareBuiltin: (struct){ a: ((string|bytes)){ "encoding/json".Valid() } } bareBuiltinCheck: (struct){ a: (string){ "3" } } builtinValidator: (struct){ a: ((string|bytes)){ "encoding/json".Valid() } } builtinValidatorCheck: (struct){ a: (string){ "3" } } callOfCallToValidator: (_|_){ // [eval] a: ((string|bytes)){ "encoding/json".Valid() } b: ((string|bytes)){ "encoding/json".Valid() } e: (_|_){ // [eval] callOfCallToValidator.e: cannot call previously called validator b: // ./in.cue:94:5 } } validatorAsFunction: (struct){ a: ((string|bytes)){ "encoding/json".Valid() } b: (bool){ true } c: (bool){ true } } issue2098: (struct){ ok1: (int){ 1 _a: (list){ 0: (int){ 1 } } } incomplete1: (_|_){ // [incomplete] issue2098.incomplete1._a: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1): // ./in.cue:112:6 // ./in.cue:111:6 // ./in.cue:112:20 _a: (_|_){ // [incomplete] issue2098.incomplete1._a: invalid value [] (does not satisfy list.MinItems(1)): len(list) < MinItems(1) (0 < 1): // ./in.cue:112:6 // ./in.cue:111:6 // ./in.cue:112:20 } } } issue3418: (_|_){ // [eval] t1: (_|_){ // [eval] issue3418.t1: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:1:24 // ./issue3418.cue:1:16 // ./issue3418.cue:1:31 // ./issue3418.cue:1:35 // ./issue3418.cue:1:37 } t2: (_|_){ // [eval] issue3418.t2: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:2:41 // ./issue3418.cue:2:16 // ./issue3418.cue:2:48 // ./issue3418.cue:2:52 // ./issue3418.cue:2:54 } t3: (_|_){ // [eval] x: (_|_){ // [eval] issue3418.t3.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:6:5 // ./issue3418.cue:4:5 // ./issue3418.cue:5:5 // ./issue3418.cue:6:12 // ./issue3418.cue:6:16 // ./issue3418.cue:6:18 } } t4: (_|_){ // [eval] x: (_|_){ // [eval] issue3418.t4.x: invalid value "foo" (does not satisfy matchN): conflicting values 2 and 1: // ./issue3418.cue:10:5 // ./issue3418.cue:9:5 // ./issue3418.cue:10:12 // ./issue3418.cue:10:16 // ./issue3418.cue:10:18 // ./issue3418.cue:11:5 } } } issue3474: (_|_){ // [eval] structValidator: (_|_){ // [eval] ok: (struct){ A: (struct){ B: (bool){ true } } } failAfter: (_|_){ // [eval] A: (_|_){ // [eval] issue3474.structValidator.failAfter.A: invalid value {C:true,B*:if true true} (does not satisfy struct.MaxFields(1)): len(fields) > MaxFields(1) (2 > 1): // ./issue3474.cue:12:5 // ./issue3474.cue:12:22 // ./issue3474.cue:13:5 C: (bool){ true } B: (bool){ true } } } incomplete: (struct){ A: (_|_){ // [incomplete] issue3474.structValidator.incomplete.A: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./issue3474.cue:20:5 // ./issue3474.cue:20:22 // ./issue3474.cue:21:5 } } failClosed: (_|_){ // [eval] #A: (_|_){ // [eval] issue3474.structValidator.failClosed.#A: invalid value {} (does not satisfy struct.MinFields(1)): len(fields) < MinFields(1) (0 < 1): // ./issue3474.cue:27:6 // ./issue3474.cue:27:23 // ./issue3474.cue:28:6 } } } topValidator: (_|_){ // [eval] ok: (struct){ A: (int){ 100 } } fail: (_|_){ // [eval] A: (_|_){ // [eval] issue3474.topValidator.fail.A: invalid value 1 (does not satisfy matchN): 0 matched, expected 1: // ./issue3474.cue:41:5 // ./issue3474.cue:41:12 // ./issue3474.cue:42:5 // ./issue3474.cue:43:12 } } incomplete: (struct){ A: (int){ &(matchN(1, (#list){ 0: (_|_){// >10 } }), int) } } failType: (_|_){ // [eval] A: (_|_){ // [eval] issue3474.topValidator.failType.A: invalid value {C:1} (does not satisfy matchN): 0 matched, expected 1: // ./issue3474.cue:53:5 // ./issue3474.cue:53:12 // ./issue3474.cue:54:5 C: (int){ 1 } } } } } issue3639: (struct){ a: (struct){ b: (int){ 1 } } #X: (_){ matchN(1, (#list){ 0: (_|_){// { // b: int // } } }) } } issue3661: (struct){ #X: (_){ matchN(1, (#list){ 0: (_|_){// { // b!: int // } } }) } a: (struct){ b: (int){ 1 } } } issue3678: (struct){ #X: (_){ matchN(1, (#list){ 0: (_|_){// { // a!: string // } } 1: (_|_){// { // c!: string // } } }) } x: (struct){ c: (string){ "c" } } y: (struct){ c: (string){ "c" } } } } -- out/compile -- --- in.cue { incompleteError1: { MyType: { kv: 〈import;struct〉.MinFields(1) } foo: (〈0;MyType〉 & { kv: { joel: "testing" } }) } incompleteError2: { MyType: { kv: { [string]: string } kv: 〈import;struct〉.MinFields(1) } foo: (〈0;MyType〉 & { kv: { joel: "testing" } }) } incompleteError3: { t: string t: 〈import;"encoding/json"〉.Validate(string) } uniqueConstrains1: { t: string t: 〈import;"encoding/json"〉.Validate(string) t: 〈import;"encoding/json"〉.Validate(string) } uniqueConstrains2: { t: 〈import;struct〉.MaxFields(1) t: 〈import;struct〉.MaxFields(1) } violation: { #MyType: { kv: { [string]: string } kv: 〈import;struct〉.MinFields(1) } foo: (〈0;#MyType〉 & { kv: { joel: "testing" } kv: { tony: "testing" } }) } conjuncts: { kv: 〈import;struct〉.MinFields(1) kv: 〈import;struct〉.MaxFields(3) } bareBuiltin: { a: 〈import;"encoding/json"〉.Valid a: 〈import;"encoding/json"〉.Valid } bareBuiltinCheck: { a: 〈import;"encoding/json"〉.Valid a: "3" } builtinValidator: { a: 〈import;"encoding/json"〉.Valid() a: 〈import;"encoding/json"〉.Valid() } builtinValidatorCheck: { a: 〈import;"encoding/json"〉.Valid() a: "3" } callOfCallToValidator: { a: 〈import;"encoding/json"〉.Valid b: 〈0;a〉() e: 〈0;b〉() e: "5" } validatorAsFunction: { a: 〈import;"encoding/json"〉.Valid b: 〈0;a〉("3") c: 〈import;"encoding/json"〉.Valid("3") } issue2098: { ok1: { _a: [ 1, ..., ] _a: 〈import;list〉.MinItems(1) 〈0;_a〉[0] } } issue2098: { incomplete1: { _a: [ ..., ] _a: 〈import;list〉.MinItems(1) 〈0;_a〉[0] } } } --- issue3418.cue { issue3418: { t1: (("foo" & matchN(1, [ (1 & 2), ])) & matchN(1, [ _, ])) } issue3418: { t2: (("foo" & matchN(1, [ _, ])) & matchN(1, [ (1 & 2), ])) } issue3418: { t3: { x: "foo" x: matchN(1, [ _, ]) x: matchN(1, [ (1 & 2), ]) } } issue3418: { t4: { x: "foo" x: matchN(1, [ (1 & 2), ]) x: matchN(1, [ _, ]) } } } --- issue3474.cue { issue3474: { structValidator: { ok: { A: 〈import;struct〉.MinFields(1) A: { if true { B: true } } } } } issue3474: { structValidator: { failAfter: { A: 〈import;struct〉.MaxFields(1) A: { C: true if true { B: true } } } } } issue3474: { structValidator: { incomplete: { A: 〈import;struct〉.MinFields(1) A: { if true {} } } } } issue3474: { structValidator: { failClosed: { #A: 〈import;struct〉.MinFields(1) #A: { if true {} } } } } issue3474: { topValidator: { ok: { A: matchN(1, [ >10, ]) A: { if true { 100 } } } } } issue3474: { topValidator: { fail: { A: matchN(1, [ >10, ]) A: { if true { 1 } } } } } issue3474: { topValidator: { incomplete: { A: matchN(1, [ >10, ]) A: { if true { int } } } } } issue3474: { topValidator: { failType: { A: matchN(1, [ >10, ]) A: { if true { C: 1 } } } } } } --- validator_is_top.cue { issue3639: { a: ({ 〈1;#X〉 } & 〈0;#X〉) a: { b: 1 } #X: matchN(1, [ { b: int }, ]) } issue3661: { #X: matchN(1, [ { b!: int }, ]) a: { b: 1 } a: 〈0;#X〉 ["a"]: 〈0;#X〉 } issue3678: { #X: matchN(1, [ { a!: string }, { c!: string }, ]) x: { c: "c" } y: 〈0;#X〉 y: 〈0;x〉 x: 〈0;#X〉 } } cue-lang-cue-db9cc73/cue/testdata/choosedefault/000077500000000000000000000000001474664451600217125ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/choosedefault/000_pick_first.txtar000066400000000000000000000014421474664451600255130ustar00rootroot00000000000000#name: pick first #bug: true #evalFull -- in.cue -- a: *5 | "a" | true b: c: *{ a: 2 } | { a: 3 } -- out/def -- a: *5 | "a" | true b: { c: *{ a: 2 } | { a: 3 } } -- out/export -- a: 5 b: { c: *{ a: 2 } | { a: 3 } } -- out/yaml -- -- out/json -- {"a":5,"b":{"c":{"a":2}}} -- out/legacy-debug -- <0>{a: 5, b: <1>{c: <2>{a: 2}}} -- out/compile -- --- in.cue { a: (*5|"a"|true) b: { c: (*{ a: 2 }|{ a: 3 }) } } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 5 Allocs: 6 Retain: 0 Unifications: 6 Conjuncts: 11 Disjuncts: 11 -- out/eval -- (struct){ a: ((bool|int|string)){ |(*(int){ 5 }, (string){ "a" }, (bool){ true }) } b: (struct){ c: (struct){ |(*(struct){ a: (int){ 2 } }, (struct){ a: (int){ 3 } }) } } } cue-lang-cue-db9cc73/cue/testdata/choosedefault/001_simple_disambiguation_conflict.txtar000066400000000000000000000011451474664451600316100ustar00rootroot00000000000000#name: simple disambiguation conflict #evalFull -- in.cue -- a: *"a" | "b" b: *"b" | "a" c: a & b -- out/def -- a: *"a" | "b" b: *"b" | "a" c: a & b -- out/legacy-debug -- <0>{a: "a", b: "b", c: ("a" | "b")} -- out/compile -- --- in.cue { a: (*"a"|"b") b: (*"b"|"a") c: (〈0;a〉 & 〈0;b〉) } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 7 Allocs: 7 Retain: 0 Unifications: 4 Conjuncts: 17 Disjuncts: 14 -- out/eval -- (struct){ a: (string){ |(*(string){ "a" }, (string){ "b" }) } b: (string){ |(*(string){ "b" }, (string){ "a" }) } c: (string){ |((string){ "a" }, (string){ "b" }) } } cue-lang-cue-db9cc73/cue/testdata/choosedefault/002_associativity_of_defaults.txtar000066400000000000000000000027201474664451600306260ustar00rootroot00000000000000#name: associativity of defaults #evalFull -- in.cue -- a: *"a" | ("b" | "c") b: (*"a" | "b") | "c" c: *"a" | (*"b" | "c") x: a & b y: b & c s1: *1 | ((*2 | 3) & (2 | *3)) s2: *1 | ((*2 | 3) & (*2 | 3)) s3: *1 | ((*2 | 3) & 3) s4: *1 | ((*2 | 3) & 2) s5: *1 | *(*2 | 3) -- out/def -- x: a & b y: b & c a: *"a" | "b" | "c" b: *"a" | "b" | "c" c: *"a" | *"b" | "c" -- out/legacy-debug -- <0>{x: "a", y: (*"a" | *"b"), a: "a", b: "a", c: (*"a" | *"b")} -- out/compile -- --- in.cue { a: (*"a"|("b"|"c")) b: ((*"a"|"b")|"c") c: (*"a"|(*"b"|"c")) x: (〈0;a〉 & 〈0;b〉) y: (〈0;b〉 & 〈0;c〉) s1: (*1|((*2|3) & (2|*3))) s2: (*1|((*2|3) & (*2|3))) s3: (*1|((*2|3) & 3)) s4: (*1|((*2|3) & 2)) s5: (*1|*(*2|3)) } -- out/eval/stats -- Leaks: 0 Freed: 83 Reused: 74 Allocs: 9 Retain: 0 Unifications: 11 Conjuncts: 93 Disjuncts: 83 -- out/eval -- (struct){ a: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } b: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } c: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } x: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } y: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } s1: (int){ |(*(int){ 1 }, (int){ 2 }, (int){ 3 }) } s2: (int){ |(*(int){ 1 }, (int){ 2 }, (int){ 3 }) } s3: (int){ |(*(int){ 1 }, (int){ 3 }) } s4: (int){ |(*(int){ 1 }, (int){ 2 }) } s5: (int){ |(*(int){ 1 }, *(int){ 2 }, (int){ 3 }) } } cue-lang-cue-db9cc73/cue/testdata/compile/000077500000000000000000000000001474664451600205155ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/compile/alias.txtar000066400000000000000000000012671474664451600227000ustar00rootroot00000000000000-- in.cue -- dynamic: t1: { X=(a): 1 x: X a: "name" } dynamic: t2: { x: X X=(a): 1 a: "name" } -- out/compile -- --- in.cue { dynamic: { t1: { 〈0;a〉: 1 x: 〈0;(〈0;a〉)〉 a: "name" } } dynamic: { t2: { x: 〈0;(〈0;a〉)〉 〈0;a〉: 1 a: "name" } } } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 5 Allocs: 5 Retain: 2 Unifications: 10 Conjuncts: 11 Disjuncts: 10 -- out/eval -- (struct){ dynamic: (struct){ t1: (struct){ x: (int){ 1 } a: (string){ "name" } name: (int){ 1 } } t2: (struct){ x: (int){ 1 } a: (string){ "name" } name: (int){ 1 } } } } cue-lang-cue-db9cc73/cue/testdata/compile/err_top.txtar000066400000000000000000000017621474664451600232610ustar00rootroot00000000000000-- in.cue -- disallowTopAsAlias: { _=X: 1 } disallowTopAsLet: { let _ = 1 } disallowTopAsLabel: { _: 1 a: _ // Should not compile to a reference. } // TODO: disallow dollar as label? This is according to the spec, but it // will be a breaking change and $ was reserved for referring to the root of // a file, which we very likely will never implement. // disallowDollarAsLabel: { // $: 1 // } -- out/compile -- disallowTopAsAlias: cannot use _ as alias or let clause: ./in.cue:2:2 disallowTopAsLet: cannot use _ as alias or let clause: ./in.cue:6:6 disallowTopAsLabel: cannot use _ as label: ./in.cue:10:2 --- in.cue { disallowTopAsAlias: { X: 1 } disallowTopAsLet: { let _ = 1 } disallowTopAsLabel: { _|_(cannot use _ as label) a: _ } } -- out/eval -- disallowTopAsAlias: cannot use _ as alias or let clause: ./in.cue:2:2 disallowTopAsLet: cannot use _ as alias or let clause: ./in.cue:6:6 disallowTopAsLabel: cannot use _ as label: ./in.cue:10:2 cue-lang-cue-db9cc73/cue/testdata/compile/erralias.txtar000066400000000000000000000007241474664451600234060ustar00rootroot00000000000000-- in.cue -- let X = {} [Y="foo"]: 3 a: Y c: {} for x in c {a: E} Z1=[Z2=string]: Z1 + Z2 -- out/compile -- unreferenced alias or let clause X: ./in.cue:1:2 a: reference "Y" not found: ./in.cue:4:12 for[].a: reference "E" not found: ./in.cue:7:16 --- in.cue { let X#1 = {} ["foo"]: 3 a: _|_(reference "Y" not found) c: {} for _, x in 〈0;c〉 { a: _|_(reference "E" not found) } [string]: (〈0;(〈0;-〉)〉 + 〈0;-〉) } cue-lang-cue-db9cc73/cue/testdata/compile/fields.txtar000066400000000000000000000005731474664451600230540ustar00rootroot00000000000000-- in.cue -- #dev: int "#dev": int _dev: int _#dev: int -- out/compile -- --- in.cue { #dev: int "#dev": int _dev: int _#dev: int } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 3 Allocs: 2 Retain: 0 Unifications: 5 Conjuncts: 5 Disjuncts: 5 -- out/eval -- (struct){ #dev: (int){ int } "#dev": (int){ int } _dev: (int){ int } _#dev: (int){ int } } cue-lang-cue-db9cc73/cue/testdata/compile/files.txtar000066400000000000000000000007531474664451600227100ustar00rootroot00000000000000// Issue #946 -- in.cue -- package repro a: [] -- out.cue -- package repro x: {for a in a {}} y: {{{for a in a {}}}} -- out/compile -- --- in.cue { a: [] } --- out.cue { x: { for _, a in 〈1;a〉 {} } y: { { { for _, a in 〈3;a〉 {} } } } } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 2 Allocs: 2 Retain: 0 Unifications: 4 Conjuncts: 7 Disjuncts: 4 -- out/eval -- (struct){ a: (#list){ } x: (struct){ } y: (struct){ } } cue-lang-cue-db9cc73/cue/testdata/compile/json.txtar000066400000000000000000000012161474664451600225520ustar00rootroot00000000000000#noformat Issue #721 -- in.cue -- // allow front-style commas a : { "key": "value" , "key2" : "value2" } , b: [ 0 , 1 , 2 ,3, 4 , 5 ] -- out/compile -- --- in.cue { a: { key: "value" key2: "value2" } b: [ 0, 1, 2, 3, 4, 5, ] } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 11 Disjuncts: 11 -- out/eval -- (struct){ a: (struct){ key: (string){ "value" } key2: (string){ "value2" } } b: (#list){ 0: (int){ 0 } 1: (int){ 1 } 2: (int){ 2 } 3: (int){ 3 } 4: (int){ 4 } 5: (int){ 5 } } } cue-lang-cue-db9cc73/cue/testdata/compile/labels.txtar000066400000000000000000000034711474664451600230500ustar00rootroot00000000000000-- in.cue -- package compile import "list" dis1: "dev" | "prd" dis2: *"dev" | "prd" con1: string let con2 = string ok0: [string]: string ok1: [name=string]: string ok2: [con1]: string ok3: [con2]: string ok4: ["foo"]: string ok5: [1]: string // disallowed in evaluator ok6: [name=1]: string // disallowed in evaluator ok7: [dis1]: string ok8: [dis2]: string ok9: [name=dis2]: string ok10: [{foo: "bar"}]: string // disallowed in evaluator ok11: [list.FlattenN([string], 1)]: string // disallowed in evaluator bad1: [for x in [1, 2, 3] {x}]: string saneReferencesInComprehensions: { for _ in [1] { a: _ // Should not compile to a reference. } } -- out/compile -- bad1: comprehension values not allowed in this position: ./in.cue:24:8 --- in.cue { dis1: ("dev"|"prd") dis2: (*"dev"|"prd") con1: string let con2#1 = string ok0: { [string]: string } ok1: { [string]: string } ok2: { [〈1;con1〉]: string } ok3: { [〈1;let con2#1〉]: string } ok4: { ["foo"]: string } ok5: { [1]: string } ok6: { [1]: string } ok7: { [〈1;dis1〉]: string } ok8: { [〈1;dis2〉]: string } ok9: { [〈1;dis2〉]: string } ok10: { [{ foo: "bar" }]: string } ok11: { [〈import;list〉.FlattenN([ string, ], 1)]: string } bad1: { [_|_(comprehension values not allowed in this position)]: string } saneReferencesInComprehensions: { for _, _ in [ 1, ] { a: _ } } } -- out/eval -- bad1: comprehension values not allowed in this position: ./in.cue:24:8 cue-lang-cue-db9cc73/cue/testdata/compile/let.txtar000066400000000000000000000033351474664451600223710ustar00rootroot00000000000000-- in.cue -- a: { let X = Y let Y = c b: X c: 5 } b: { let X = Y let Y = X b: X c: 5 } fieldOffset: { a: { p1: { let X = {value: Y} let Y = 2 x: X } p2: { x: X let Y = 2 let X = {value: Y} } } b: { p1: { let X = {x: y: Y} let Y = 2 x: X } p2: { x: X let Y = 2 let X = {x: y: Y} } } } issue767: { #Foo: { let _#bar = { value: "" } let _#volmnts = { x: _#baz.value } let _#baz = { _#bar } out: _#volmnts } } -- out/compile -- b.let[]: cyclic references in let clause or alias: ./in.cue:10:10 --- in.cue { a: { let X#1 = 〈0;let Y#2〉 let Y#2 = 〈0;c〉 b: 〈0;let X#1〉 c: 5 } b: { let X#3 = 〈0;let Y#4〉 let Y#4 = 〈0;let X#3〉 b: 〈0;let X#3〉 c: 5 } fieldOffset: { a: { p1: { let X#5 = { value: 〈1;let Y#6〉 } let Y#6 = 2 x: 〈0;let X#5〉 } p2: { x: 〈0;let X#8〉 let Y#7 = 2 let X#8 = { value: 〈1;let Y#7〉 } } } b: { p1: { let X#9 = { x: { y: 〈2;let Y#A〉 } } let Y#A = 2 x: 〈0;let X#9〉 } p2: { x: 〈0;let X#C〉 let Y#B = 2 let X#C = { x: { y: 〈2;let Y#B〉 } } } } } issue767: { #Foo: { let _#bar#D = { value: "" } let _#volmnts#E = { x: 〈1;let _#baz#F〉.value } let _#baz#F = { 〈1;let _#bar#D〉 } out: 〈0;let _#volmnts#E〉 } } } -- out/eval -- b.let[]: cyclic references in let clause or alias: ./in.cue:10:10 cue-lang-cue-db9cc73/cue/testdata/compile/scope.txtar000066400000000000000000000052151474664451600227150ustar00rootroot00000000000000-- in.cue -- a: { {{ b c d: b e: c }} c: {} } b: { } s: "foo" c: s // s is technically in a new struct here so it will have a one higher count than // the one before. d: [s]: 3 e: {} e & {// Is this allowed? Probably not as per comprehension rule (ref fixes.) e: {} } {X=["foo"]: b: X | null} {[Y="bar"]: b: Y} let B = {open: int} f: B schema: { next: _schema_1 } let _schema_1 = schema -- out/compile -- --- in.cue { a: { { { 〈3;b〉 〈2;c〉 d: 〈3;b〉 e: 〈2;c〉 } } c: {} } b: {} s: "foo" c: 〈0;s〉 d: { [〈1;s〉]: 3 } e: {} (〈0;e〉 & { e: {} }) { ["foo"]: { b: (〈1;(〈0;-〉)〉|null) } } { ["bar"]: { b: 〈1;-〉 } } let B#1 = { open: int } f: 〈0;let B#1〉 schema: { next: 〈1;let _schema_1#2〉 } let _schema_1#2 = 〈0;schema〉 } -- out/eval/stats -- Leaks: 2 Freed: 48 Reused: 45 Allocs: 5 Retain: 8 Unifications: 50 Conjuncts: 102 Disjuncts: 54 -- out/evalalpha -- Errors: schema.next: structural cycle Result: (_|_){ // [structural cycle] a: (struct){ d: (struct){ } e: (struct){ } c: (struct){ } } b: (struct){ } s: (string){ "foo" } c: (string){ "foo" } d: (struct){ } e: (struct){ } let B#1 = (struct){ open: (int){ int } } f: (struct){ open: (int){ int } } schema: (_|_){ // [structural cycle] next: (_|_){ // [structural cycle] schema.next: structural cycle } } let _schema_1#2 = (_|_){ // [structural cycle] _schema_1: structural cycle } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -33,7 +33,6 @@ } } let _schema_1#2 = (_|_){ - // [structural cycle] _schema_1: structural cycle: - // ./in.cue:32:8 + // [structural cycle] _schema_1: structural cycle } } -- diff/todo/p3 -- Structural cycle reported in different location. Seems fine, as ultimately we need to print the paths of the cycle anyway. Now also reports a position. -- out/eval -- Errors: schema.next: structural cycle Result: (_|_){ // [structural cycle] a: (struct){ d: (struct){ } e: (struct){ } c: (struct){ } } b: (struct){ } s: (string){ "foo" } c: (string){ "foo" } d: (struct){ } e: (struct){ } let B#1 = (struct){ open: (int){ int } } f: (struct){ open: (int){ int } } schema: (_|_){ // [structural cycle] next: (_|_){ // [structural cycle] schema.next: structural cycle } } let _schema_1#2 = (_|_){ // [structural cycle] _schema_1: structural cycle: // ./in.cue:32:8 } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/000077500000000000000000000000001474664451600221215ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/comprehensions/015_list_comprehension.txtar000066400000000000000000000027551474664451600275070ustar00rootroot00000000000000#name: list comprehension #evalFull -- in.cue -- a: [for k, v in b if k < "d" if v > b.a {k}] b: { a: 1 b: 2 c: 3 d: 4 } c: [for _, x in b for _, y in b if x < y {x}] d: [for x, _ in a {x}] -- out/def -- a: ["b", "c"] b: { a: 1 b: 2 c: 3 d: 4 } c: [1, 1, 1, 2, 2, 3] d: [0, 1] -- out/export -- a: ["b", "c"] b: { a: 1 b: 2 c: 3 d: 4 } c: [1, 1, 1, 2, 2, 3] d: [0, 1] -- out/yaml -- a: - b - c b: a: 1 b: 2 c: 3 d: 4 c: - 1 - 1 - 1 - 2 - 2 - 3 d: - 0 - 1 -- out/json -- {"a":["b","c"],"b":{"a":1,"b":2,"c":3,"d":4},"c":[1,1,1,2,2,3],"d":[0,1]} -- out/legacy-debug -- <0>{a: ["b","c"], b: <1>{a: 1, b: 2, c: 3, d: 4}, c: [1,1,1,2,2,3], d: [0,1]} -- out/compile -- --- in.cue { a: [ for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { 〈1;k〉 }, ] b: { a: 1 b: 2 c: 3 d: 4 } c: [ for _, x in 〈1;b〉 for _, y in 〈2;b〉 if (〈1;x〉 < 〈0;y〉) { 〈2;x〉 }, ] d: [ for x, _ in 〈1;a〉 { 〈1;x〉 }, ] } -- out/eval/stats -- Leaks: 0 Freed: 19 Reused: 12 Allocs: 7 Retain: 10 Unifications: 19 Conjuncts: 36 Disjuncts: 23 -- out/eval -- (struct){ a: (#list){ 0: (string){ "b" } 1: (string){ "c" } } b: (struct){ a: (int){ 1 } b: (int){ 2 } c: (int){ 3 } d: (int){ 4 } } c: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 2 } 4: (int){ 2 } 5: (int){ 3 } } d: (#list){ 0: (int){ 0 } 1: (int){ 1 } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/045_comprehension_and_skipped_field.txtar000066400000000000000000000015211474664451600321510ustar00rootroot00000000000000#name: comprehension and skipped field #bug: true #evalFull -- in.cue -- for key, value in {x: v: 1} { "\(key)": { v: *{for pod, _ in value.v {}} | {"\(value.v)": 2} _p: 3 } } -- out/def -- x: { v: { "1": 2 } _p: 3 } -- out/export -- x: { v: { "1": 2 } } -- out/yaml -- x: v: "1": 2 -- out/json -- -- out/legacy-debug -- <0>{x: <1>{v: <2>{"1": 2}, _p: 3}} -- out/compile -- --- in.cue { for key, value in { x: { v: 1 } } { "\(〈1;key〉)": { v: (*{ for pod, _ in 〈3;value〉.v {} }|{ "\(〈3;value〉.v)": 2 }) _p: 3 } } } -- out/eval/stats -- Leaks: 3 Freed: 7 Reused: 2 Allocs: 8 Retain: 7 Unifications: 8 Conjuncts: 11 Disjuncts: 12 -- out/eval -- (struct){ x: (struct){ v: (struct){ "1": (int){ 2 } } _p: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/checkdefined.txtar000066400000000000000000000162351474664451600256100ustar00rootroot00000000000000 Issue #1969 -- in.cue -- import "list" // All tests here should pass and the result of the okcN tests should be // identical to those of the okoN tests. xc: close({field: {}}) xo: field: {} okc0: { if xc.undefined == _|_ {a: 1} } oko0: { if xo.undefined == _|_ {a: 1} } okc1: { if xc.undefined != _|_ {a: 1} } oko1: { if xo.undefined != _|_ {a: 1} } okc2: { if ({} & {s: [for y in xc.undefined {}]}) != _|_ {a: 1} } oko2: { if ({} & {s: [for y in xo.undefined {}]}) != _|_ {a: 1} } okc3: { if ({s: [for y in xc.undefined {}]}) != _|_ {a: 1} } oko3: { if ({s: [for y in xo.undefined {}]}) != _|_ {a: 1} } // Should Field s exist in okc or not? Depends on whether comparison to bottom // is recursive or not. It probably should not. // TODO: fix for new evaluator. But possibly address this with new builtins. issue1969: okc: { let X = xc.undefined let Y = {} & {s: [for y in list.Range(0, X, 1) {}]} if Y != _|_ {Y} } issue1969: oko: { let X = xo.undefined let Y = {} & {s: [for y in list.Range(0, X, 1) {}]} if Y != _|_ {Y} } -- issue2245.cue -- yo: { f: int, g: f < 10 } okyo: { if yo != _|_ {a: 1} } okyog: { if yo.g != _|_ {a: 1} } -- incomplete.cue -- // Comparing to string is not an error. But for legacy reasons we want to still // support this. We intend to have more clean and precise behavior with the // builtins isdefined, isvalid, and isconcrete. checkIncomplete: t1: { f: [string]: { if a != _|_ { b: "d\(a)" } a: string } f: blah: {} } -- structs.cue -- structs: { bare: t1: ({y: 2} & {x: 3}) != _|_ bare: f2: ({y: 2} & {x: 3}) == _|_ bare: f3: ({x: 1, y: 2} & {x: 3}) != _|_ bare: t4: ({x: 1, y: 2} & {x: 3}) == _|_ select: t1: ({y: 2} & {x: 3}).y != _|_ select: f2: ({y: 2} & {x: 3}).y == _|_ select: f3: ({x: 1, y: 2} & {x: 3}).y != _|_ select: t4: ({x: 1, y: 2} & {x: 3}).y == _|_ } -- out/eval/stats -- Leaks: 11 Freed: 89 Reused: 85 Allocs: 15 Retain: 26 Unifications: 100 Conjuncts: 134 Disjuncts: 105 -- out/eval -- (struct){ xc: (#struct){ field: (struct){ } } xo: (struct){ field: (struct){ } } okc0: (struct){ a: (int){ 1 } } oko0: (struct){ a: (int){ 1 } } okc1: (struct){ } oko1: (struct){ } okc2: (struct){ } oko2: (struct){ a: (int){ 1 } } okc3: (struct){ } oko3: (struct){ a: (int){ 1 } } issue1969: (struct){ okc: (struct){ let X#1 = (_|_){ // [eval] issue1969.okc.X: undefined field: undefined: // ./in.cue:35:13 } let Y#2 = (_|_){ // [eval] s: (_|_){ // [eval] issue1969.okc.X: undefined field: undefined: // ./in.cue:35:13 } } } oko: (struct){ let X#3 = (_|_){ // [incomplete] issue1969.oko.X: undefined field: undefined: // ./in.cue:42:13 } let Y#4 = (struct){ s: (_|_){ // [incomplete] issue1969.oko.X: undefined field: undefined: // ./in.cue:42:13 } } s: (_|_){ // [incomplete] issue1969.oko.X: undefined field: undefined: // ./in.cue:42:13 } } } checkIncomplete: (struct){ t1: (struct){ f: (struct){ blah: (struct){ a: (string){ string } } } } } yo: (struct){ f: (int){ int } g: (_|_){ // [incomplete] yo.g: non-concrete value int in operand to <: // ./issue2245.cue:1:18 // ./issue2245.cue:1:10 } } okyo: (struct){ a: (int){ 1 } } okyog: (struct){ } structs: (struct){ bare: (struct){ t1: (bool){ true } f2: (bool){ false } f3: (bool){ false } t4: (bool){ true } } select: (struct){ t1: (bool){ true } f2: (bool){ false } f3: (bool){ false } t4: (bool){ true } } } } -- out/compile -- --- in.cue { xc: close({ field: {} }) xo: { field: {} } okc0: { if (〈1;xc〉.undefined == _|_(explicit error (_|_ literal) in source)) { a: 1 } } oko0: { if (〈1;xo〉.undefined == _|_(explicit error (_|_ literal) in source)) { a: 1 } } okc1: { if (〈1;xc〉.undefined != _|_(explicit error (_|_ literal) in source)) { a: 1 } } oko1: { if (〈1;xo〉.undefined != _|_(explicit error (_|_ literal) in source)) { a: 1 } } okc2: { if (({} & { s: [ for _, y in 〈3;xc〉.undefined {}, ] }) != _|_(explicit error (_|_ literal) in source)) { a: 1 } } oko2: { if (({} & { s: [ for _, y in 〈3;xo〉.undefined {}, ] }) != _|_(explicit error (_|_ literal) in source)) { a: 1 } } okc3: { if ({ s: [ for _, y in 〈3;xc〉.undefined {}, ] } != _|_(explicit error (_|_ literal) in source)) { a: 1 } } oko3: { if ({ s: [ for _, y in 〈3;xo〉.undefined {}, ] } != _|_(explicit error (_|_ literal) in source)) { a: 1 } } issue1969: { okc: { let X#1 = 〈2;xc〉.undefined let Y#2 = ({} & { s: [ for _, y in 〈import;list〉.Range(0, 〈2;let X#1〉, 1) {}, ] }) if (〈0;let Y#2〉 != _|_(explicit error (_|_ literal) in source)) { 〈1;let Y#2〉 } } } issue1969: { oko: { let X#3 = 〈2;xo〉.undefined let Y#4 = ({} & { s: [ for _, y in 〈import;list〉.Range(0, 〈2;let X#3〉, 1) {}, ] }) if (〈0;let Y#4〉 != _|_(explicit error (_|_ literal) in source)) { 〈1;let Y#4〉 } } } } --- incomplete.cue { checkIncomplete: { t1: { f: { [string]: { if (〈0;a〉 != _|_(explicit error (_|_ literal) in source)) { b: "d\(〈1;a〉)" } a: string } } f: { blah: {} } } } } --- issue2245.cue { yo: { f: int g: (〈0;f〉 < 10) } okyo: { if (〈1;yo〉 != _|_(explicit error (_|_ literal) in source)) { a: 1 } } okyog: { if (〈1;yo〉.g != _|_(explicit error (_|_ literal) in source)) { a: 1 } } } --- structs.cue { structs: { bare: { t1: (({ y: 2 } & { x: 3 }) != _|_(explicit error (_|_ literal) in source)) } bare: { f2: (({ y: 2 } & { x: 3 }) == _|_(explicit error (_|_ literal) in source)) } bare: { f3: (({ x: 1 y: 2 } & { x: 3 }) != _|_(explicit error (_|_ literal) in source)) } bare: { t4: (({ x: 1 y: 2 } & { x: 3 }) == _|_(explicit error (_|_ literal) in source)) } select: { t1: (({ y: 2 } & { x: 3 }).y != _|_(explicit error (_|_ literal) in source)) } select: { f2: (({ y: 2 } & { x: 3 }).y == _|_(explicit error (_|_ literal) in source)) } select: { f3: (({ x: 1 y: 2 } & { x: 3 }).y != _|_(explicit error (_|_ literal) in source)) } select: { t4: (({ x: 1 y: 2 } & { x: 3 }).y == _|_(explicit error (_|_ literal) in source)) } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/closed.txtar000066400000000000000000000257241474664451600244700ustar00rootroot00000000000000-- in.cue -- dynamicTop: { #D: { for k, v in {foo: 123} {(k): v} } } // Issue #1404 dynamicDepth1: { #D: { a: foo: 123 b: {for k, v in a {(k): v}} } } allowed: { #D: { if true { d: int } } vErr: #D & {d: 5} } disallowed: { #D: { if false { d: int } } vErr: #D & {d: 5} } // Interpret comprehensions as embeddings. // Issue #1956 comprehensionIsEmbed: { #A: size: int | *1 #B: { kind: string // Should be identical to just #A. That is, #A is treated as open. if true { #A } } x: #B & { kind: "A" } } // This comprehension is inside a definition and should still disallow b. noEraseDefinition: { #Foo: [if true {a: int}] a: { #Foo & [{ b: 2 }] } // Error } issue1956: { #Details: { size: int | *1 } #Thing: { kind: "KindA" | "KindB" if kind == "KindA" { #Details } } x: #Thing & { kind: "KindA" } } // This triggers adding the same "closedInfo" twice, potentially causing // a cyclic linked list in the todo list. dedupTodo: { #sub: { c: _ if c.n == "c" { X: test: c } } out: #sub // needs to be definition out: { c: n: "c" // Do not combine with &, as the original issue relies on this. c: n: string } } -- v3issues.cue -- issue3483: { #Schema: schemaField: int out1: out2: #Schema & { if false { schemaField: 3 } } } issue3486: { #schema: {} if true { out: { #schema // This field should be allowed as #schema is embedded. extra: "foo" } } } -- out/eval/stats -- Leaks: 2 Freed: 80 Reused: 74 Allocs: 8 Retain: 3 Unifications: 68 Conjuncts: 118 Disjuncts: 81 -- out/evalalpha -- Errors: noEraseDefinition.a.0.b: field not allowed: ./in.cue:55:17 disallowed.vErr.d: field not allowed: ./in.cue:28:7 ./in.cue:28:4 ./in.cue:32:14 Result: (_|_){ // [eval] dynamicTop: (struct){ #D: (#struct){ foo: (int){ 123 } } } dynamicDepth1: (struct){ #D: (#struct){ a: (#struct){ foo: (int){ 123 } } b: (#struct){ foo: (int){ 123 } } } } allowed: (struct){ #D: (#struct){ d: (int){ int } } vErr: (#struct){ d: (int){ 5 } } } disallowed: (_|_){ // [eval] #D: (#struct){ } vErr: (_|_){ // [eval] d: (_|_){ // [eval] disallowed.vErr.d: field not allowed: // ./in.cue:28:7 // ./in.cue:28:4 // ./in.cue:32:14 } } } comprehensionIsEmbed: (struct){ #A: (#struct){ size: (int){ |(*(int){ 1 }, (int){ int }) } } #B: (#struct){ kind: (string){ string } size: (int){ |(*(int){ 1 }, (int){ int }) } } x: (#struct){ kind: (string){ "A" } size: (int){ |(*(int){ 1 }, (int){ int }) } } } noEraseDefinition: (_|_){ // [eval] #Foo: (#list){ 0: (#struct){ a: (int){ int } } } a: (_|_){ // [eval] 0: (_|_){ // [eval] b: (_|_){ // [eval] noEraseDefinition.a.0.b: field not allowed: // ./in.cue:55:17 } a: (int){ int } } } } issue1956: (struct){ #Details: (#struct){ size: (int){ |(*(int){ 1 }, (int){ int }) } } #Thing: (_|_){ // [incomplete] issue1956.#Thing: unresolved disjunction "KindA" | "KindB" (type string): // ./in.cue:65:6 kind: (string){ |((string){ "KindA" }, (string){ "KindB" }) } } x: (#struct){ kind: (string){ "KindA" } size: (int){ |(*(int){ 1 }, (int){ int }) } } } dedupTodo: (struct){ #sub: (_|_){ // [incomplete] dedupTodo.#sub: c.n undefined as c is incomplete (type _): // ./in.cue:80:6 c: (_){ _ } } out: (#struct){ c: (#struct){ n: (string){ "c" } } X: (#struct){ test: ~(dedupTodo.out.c) } } } issue3483: (struct){ #Schema: (#struct){ schemaField: (int){ int } } out1: (struct){ out2: (#struct){ schemaField: (int){ int } } } } issue3486: (struct){ #schema: (#struct){ } out: (#struct){ extra: (string){ "foo" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,20 +1,10 @@ Errors: +noEraseDefinition.a.0.b: field not allowed: + ./in.cue:55:17 disallowed.vErr.d: field not allowed: - ./in.cue:26:6 - ./in.cue:27:3 - ./in.cue:27:12 + ./in.cue:28:7 ./in.cue:28:4 - ./in.cue:32:8 ./in.cue:32:14 -issue3486.out.extra: field not allowed: - ./v3issues.cue:10:11 - ./v3issues.cue:12:2 - ./v3issues.cue:14:4 - ./v3issues.cue:16:4 -noEraseDefinition.a.0.b: field not allowed: - ./in.cue:54:17 - ./in.cue:55:7 - ./in.cue:55:17 Result: (_|_){ @@ -50,11 +40,8 @@ // [eval] d: (_|_){ // [eval] disallowed.vErr.d: field not allowed: - // ./in.cue:26:6 - // ./in.cue:27:3 - // ./in.cue:27:12 + // ./in.cue:28:7 // ./in.cue:28:4 - // ./in.cue:32:8 // ./in.cue:32:14 } } @@ -83,13 +70,11 @@ // [eval] 0: (_|_){ // [eval] - a: (int){ int } b: (_|_){ // [eval] noEraseDefinition.a.0.b: field not allowed: - // ./in.cue:54:17 - // ./in.cue:55:7 // ./in.cue:55:17 } + a: (int){ int } } } } @@ -114,13 +99,11 @@ c: (_){ _ } } out: (#struct){ - c: (struct){ + c: (#struct){ n: (string){ "c" } } X: (#struct){ - test: (#struct){ - n: (string){ "c" } - } + test: ~(dedupTodo.out.c) } } } @@ -134,19 +117,11 @@ } } } - issue3486: (_|_){ - // [eval] + issue3486: (struct){ #schema: (#struct){ } - out: (_|_){ - // [eval] - extra: (_|_){ - // [eval] issue3486.out.extra: field not allowed: - // ./v3issues.cue:10:11 - // ./v3issues.cue:12:2 - // ./v3issues.cue:14:4 - // ./v3issues.cue:16:4 - } + out: (#struct){ + extra: (string){ "foo" } } } } -- diff/todo/p3 -- Missing error positions. -- diff/explanation -- dedupTodo.out.c: the new evaluator correctly marks this as closed. -- out/eval -- Errors: disallowed.vErr.d: field not allowed: ./in.cue:26:6 ./in.cue:27:3 ./in.cue:27:12 ./in.cue:28:4 ./in.cue:32:8 ./in.cue:32:14 issue3486.out.extra: field not allowed: ./v3issues.cue:10:11 ./v3issues.cue:12:2 ./v3issues.cue:14:4 ./v3issues.cue:16:4 noEraseDefinition.a.0.b: field not allowed: ./in.cue:54:17 ./in.cue:55:7 ./in.cue:55:17 Result: (_|_){ // [eval] dynamicTop: (struct){ #D: (#struct){ foo: (int){ 123 } } } dynamicDepth1: (struct){ #D: (#struct){ a: (#struct){ foo: (int){ 123 } } b: (#struct){ foo: (int){ 123 } } } } allowed: (struct){ #D: (#struct){ d: (int){ int } } vErr: (#struct){ d: (int){ 5 } } } disallowed: (_|_){ // [eval] #D: (#struct){ } vErr: (_|_){ // [eval] d: (_|_){ // [eval] disallowed.vErr.d: field not allowed: // ./in.cue:26:6 // ./in.cue:27:3 // ./in.cue:27:12 // ./in.cue:28:4 // ./in.cue:32:8 // ./in.cue:32:14 } } } comprehensionIsEmbed: (struct){ #A: (#struct){ size: (int){ |(*(int){ 1 }, (int){ int }) } } #B: (#struct){ kind: (string){ string } size: (int){ |(*(int){ 1 }, (int){ int }) } } x: (#struct){ kind: (string){ "A" } size: (int){ |(*(int){ 1 }, (int){ int }) } } } noEraseDefinition: (_|_){ // [eval] #Foo: (#list){ 0: (#struct){ a: (int){ int } } } a: (_|_){ // [eval] 0: (_|_){ // [eval] a: (int){ int } b: (_|_){ // [eval] noEraseDefinition.a.0.b: field not allowed: // ./in.cue:54:17 // ./in.cue:55:7 // ./in.cue:55:17 } } } } issue1956: (struct){ #Details: (#struct){ size: (int){ |(*(int){ 1 }, (int){ int }) } } #Thing: (_|_){ // [incomplete] issue1956.#Thing: unresolved disjunction "KindA" | "KindB" (type string): // ./in.cue:65:6 kind: (string){ |((string){ "KindA" }, (string){ "KindB" }) } } x: (#struct){ kind: (string){ "KindA" } size: (int){ |(*(int){ 1 }, (int){ int }) } } } dedupTodo: (struct){ #sub: (_|_){ // [incomplete] dedupTodo.#sub: c.n undefined as c is incomplete (type _): // ./in.cue:80:6 c: (_){ _ } } out: (#struct){ c: (struct){ n: (string){ "c" } } X: (#struct){ test: (#struct){ n: (string){ "c" } } } } } issue3483: (struct){ #Schema: (#struct){ schemaField: (int){ int } } out1: (struct){ out2: (#struct){ schemaField: (int){ int } } } } issue3486: (_|_){ // [eval] #schema: (#struct){ } out: (_|_){ // [eval] extra: (_|_){ // [eval] issue3486.out.extra: field not allowed: // ./v3issues.cue:10:11 // ./v3issues.cue:12:2 // ./v3issues.cue:14:4 // ./v3issues.cue:16:4 } } } } -- out/compile -- --- in.cue { dynamicTop: { #D: { for k, v in { foo: 123 } { 〈1;k〉: 〈1;v〉 } } } dynamicDepth1: { #D: { a: { foo: 123 } b: { for k, v in 〈1;a〉 { 〈1;k〉: 〈1;v〉 } } } } allowed: { #D: { if true { d: int } } vErr: (〈0;#D〉 & { d: 5 }) } disallowed: { #D: { if false { d: int } } vErr: (〈0;#D〉 & { d: 5 }) } comprehensionIsEmbed: { #A: { size: (int|*1) } #B: { kind: string if true { 〈2;#A〉 } } x: (〈0;#B〉 & { kind: "A" }) } noEraseDefinition: { #Foo: [ if true { a: int }, ] a: { (〈1;#Foo〉 & [ { b: 2 }, ]) } } issue1956: { #Details: { size: (int|*1) } #Thing: { kind: ("KindA"|"KindB") if (〈0;kind〉 == "KindA") { 〈2;#Details〉 } } x: (〈0;#Thing〉 & { kind: "KindA" }) } dedupTodo: { #sub: { c: _ if (〈0;c〉.n == "c") { X: { test: 〈2;c〉 } } } out: 〈0;#sub〉 out: { c: { n: "c" } c: { n: string } } } } --- v3issues.cue { issue3483: { #Schema: { schemaField: int } out1: { out2: (〈1;#Schema〉 & { if false { schemaField: 3 } }) } } issue3486: { #schema: {} if true { out: { 〈2;#schema〉 extra: "foo" } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/errors.txtar000066400000000000000000000116761474664451600245340ustar00rootroot00000000000000-- in.cue -- circularIf: { #list: { tail: #list | *null if tail != null { } } } circularFor: { #list: { tail: #list | *null for x in tail != null { } } } // Print a bit more sensible error message than "empty disjunction" here. // Issue #465 userError: { a: string | *_|_ if a != "" { } } intField: { for i, _ in [1, 2] { (i): { } } } // Issue #2403 conflictRangingOverSelf: { x: { name: string age: int } x: { for k, _ in x { (k): k } } } -- out/eval/stats -- Leaks: 1 Freed: 28 Reused: 22 Allocs: 7 Retain: 1 Unifications: 19 Conjuncts: 40 Disjuncts: 29 -- out/evalalpha -- Errors: conflictRangingOverSelf.x.age: conflicting values int and "age" (mismatched types int and string): ./in.cue:36:9 ./in.cue:40:3 circularFor.#list: cannot range over tail != null (found bool, want list or struct): ./in.cue:12:12 intField: integer fields not supported: ./in.cue:27:4 Result: (_|_){ // [eval] circularIf: (struct){ #list: (#struct){ tail: (null){ null } } } circularFor: (_|_){ // [eval] #list: (_|_){ // [eval] circularFor.#list: cannot range over tail != null (found bool, want list or struct): // ./in.cue:12:12 tail: (null){ null } } } userError: (_|_){ // [incomplete] userError: non-concrete value string in operand to !=: // ./in.cue:21:5 // ./in.cue:20:5 a: (string){ string } } intField: (_|_){ // [eval] intField: integer fields not supported: // ./in.cue:27:4 } conflictRangingOverSelf: (_|_){ // [eval] x: (_|_){ // [eval] name: (string){ "name" } age: (_|_){ // [eval] conflictRangingOverSelf.x.age: conflicting values int and "age" (mismatched types int and string): // ./in.cue:36:9 // ./in.cue:40:3 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,7 +2,6 @@ conflictRangingOverSelf.x.age: conflicting values int and "age" (mismatched types int and string): ./in.cue:36:9 ./in.cue:40:3 - ./in.cue:41:9 circularFor.#list: cannot range over tail != null (found bool, want list or struct): ./in.cue:12:12 intField: integer fields not supported: @@ -13,9 +12,7 @@ // [eval] circularIf: (struct){ #list: (#struct){ - tail: ((null|struct)){ |(*(null){ null }, (#struct){ - tail: (null){ null } - }) } + tail: (null){ null } } } circularFor: (_|_){ @@ -35,10 +32,6 @@ intField: (_|_){ // [eval] intField: integer fields not supported: // ./in.cue:27:4 - 0: (struct){ - } - 1: (struct){ - } } conflictRangingOverSelf: (_|_){ // [eval] @@ -49,7 +42,6 @@ // [eval] conflictRangingOverSelf.x.age: conflicting values int and "age" (mismatched types int and string): // ./in.cue:36:9 // ./in.cue:40:3 - // ./in.cue:41:9 } } } -- diff/todo/p2 -- Missing error message. -- out/eval -- Errors: conflictRangingOverSelf.x.age: conflicting values int and "age" (mismatched types int and string): ./in.cue:36:9 ./in.cue:40:3 ./in.cue:41:9 circularFor.#list: cannot range over tail != null (found bool, want list or struct): ./in.cue:12:12 intField: integer fields not supported: ./in.cue:27:4 Result: (_|_){ // [eval] circularIf: (struct){ #list: (#struct){ tail: ((null|struct)){ |(*(null){ null }, (#struct){ tail: (null){ null } }) } } } circularFor: (_|_){ // [eval] #list: (_|_){ // [eval] circularFor.#list: cannot range over tail != null (found bool, want list or struct): // ./in.cue:12:12 tail: (null){ null } } } userError: (_|_){ // [incomplete] userError: non-concrete value string in operand to !=: // ./in.cue:21:5 // ./in.cue:20:5 a: (string){ string } } intField: (_|_){ // [eval] intField: integer fields not supported: // ./in.cue:27:4 0: (struct){ } 1: (struct){ } } conflictRangingOverSelf: (_|_){ // [eval] x: (_|_){ // [eval] name: (string){ "name" } age: (_|_){ // [eval] conflictRangingOverSelf.x.age: conflicting values int and "age" (mismatched types int and string): // ./in.cue:36:9 // ./in.cue:40:3 // ./in.cue:41:9 } } } } -- out/compile -- --- in.cue { circularIf: { #list: { tail: (〈1;#list〉|*null) if (〈0;tail〉 != null) {} } } circularFor: { #list: { tail: (〈1;#list〉|*null) for _, x in (〈0;tail〉 != null) {} } } userError: { a: (string|*_|_(explicit error (_|_ literal) in source)) if (〈0;a〉 != "") {} } intField: { for i, _ in [ 1, 2, ] { 〈1;i〉: {} } } conflictRangingOverSelf: { x: { name: string age: int } x: { for k, _ in 〈1;x〉 { 〈1;k〉: 〈1;k〉 } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/fields.txtar000066400000000000000000000105761474664451600244640ustar00rootroot00000000000000Issue #560 -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- import "strings" dynamic: { for _, s in ["foo"] { (s): 1 "\(s)bar": 2 } } ignoreOptional: { #x: { a?: string b?: string c: string } y: { for k,v in #x { (k): "exists" } } } missingRequiredError: { // Issue #2369 #x: { a!: string b?: string c: string } y: { for k,v in #x { (k): "exists" } } } issue560: { #User: { tags_str: string tags_map: { for k, v in strings.Split(tags_str, " ") { "\(v)": string } "{a}": string } } user: { #User tags_str: "b {c}" } } -- out/eval/stats -- Leaks: 1 Freed: 29 Reused: 24 Allocs: 6 Retain: 1 Unifications: 30 Conjuncts: 38 Disjuncts: 30 -- out/evalalpha -- (struct){ dynamic: (struct){ foo: (int){ 1 } foobar: (int){ 2 } } ignoreOptional: (struct){ #x: (#struct){ a?: (string){ string } b?: (string){ string } c: (string){ string } } y: (struct){ c: (string){ "exists" } } } missingRequiredError: (struct){ #x: (#struct){ a!: (string){ string } b?: (string){ string } c: (string){ string } } y: (_|_){ // [incomplete] missingRequiredError.y: missing required field in for comprehension: a: // ./in.cue:33:3 // ./in.cue:27:3 // ./in.cue:33:14 // missingRequiredError.y: key value of dynamic field must be concrete, found _|_(missingRequiredError.y: missing required field in for comprehension: a): // ./in.cue:34:5 } } issue560: (struct){ #User: (#struct){ tags_str: (string){ string } tags_map: (_|_){ // [incomplete] issue560.#User.tags_map: error in call to strings.Split: non-concrete value string: // ./in.cue:43:16 // ./in.cue:41:13 "{a}": (string){ string } } } user: (#struct){ tags_str: (string){ "b {c}" } tags_map: (#struct){ "{a}": (string){ string } b: (string){ string } "{c}": (string){ string } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -24,6 +24,8 @@ // ./in.cue:33:3 // ./in.cue:27:3 // ./in.cue:33:14 + // missingRequiredError.y: key value of dynamic field must be concrete, found _|_(missingRequiredError.y: missing required field in for comprehension: a): + // ./in.cue:34:5 } } issue560: (struct){ -- diff/todo/p2 -- Near-duplicate message -- out/eval -- (struct){ dynamic: (struct){ foo: (int){ 1 } foobar: (int){ 2 } } ignoreOptional: (struct){ #x: (#struct){ a?: (string){ string } b?: (string){ string } c: (string){ string } } y: (struct){ c: (string){ "exists" } } } missingRequiredError: (struct){ #x: (#struct){ a!: (string){ string } b?: (string){ string } c: (string){ string } } y: (_|_){ // [incomplete] missingRequiredError.y: missing required field in for comprehension: a: // ./in.cue:33:3 // ./in.cue:27:3 // ./in.cue:33:14 } } issue560: (struct){ #User: (#struct){ tags_str: (string){ string } tags_map: (_|_){ // [incomplete] issue560.#User.tags_map: error in call to strings.Split: non-concrete value string: // ./in.cue:43:16 // ./in.cue:41:13 "{a}": (string){ string } } } user: (#struct){ tags_str: (string){ "b {c}" } tags_map: (#struct){ "{a}": (string){ string } b: (string){ string } "{c}": (string){ string } } } } } -- out/compile -- --- in.cue { dynamic: { for _, s in [ "foo", ] { 〈1;s〉: 1 "\(〈1;s〉)bar": 2 } } ignoreOptional: { #x: { a?: string b?: string c: string } y: { for k, v in 〈1;#x〉 { 〈1;k〉: "exists" } } } missingRequiredError: { #x: { a!: string b?: string c: string } y: { for k, v in 〈1;#x〉 { 〈1;k〉: "exists" } } } issue560: { #User: { tags_str: string tags_map: { for k, v in 〈import;strings〉.Split(〈1;tags_str〉, " ") { "\(〈1;v〉)": string } "{a}": string } } user: { 〈1;#User〉 tags_str: "b {c}" } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/for.txtar000066400000000000000000000025571474664451600240040ustar00rootroot00000000000000-- in.cue -- b: {for k, v in a {"\(k)": v + 1}} a: {b: 1, c: 2} x: {for k, v in y {"\(k)": v}} y: {} // check that empty struct after reference works. k: {for v in e {v}} e: int comprehensionBinds: { a: {for _ in [1] {a: _}} b: {for _, _ in [1] {a: _}} } -- out/eval/stats -- Leaks: 2 Freed: 16 Reused: 12 Allocs: 6 Retain: 7 Unifications: 18 Conjuncts: 18 Disjuncts: 21 -- out/eval -- Errors: k: cannot range over e (found int, want list or struct): ./in.cue:7:14 Result: (_|_){ // [eval] b: (struct){ b: (int){ 2 } c: (int){ 3 } } a: (struct){ b: (int){ 1 } c: (int){ 2 } } x: (struct){ } y: (struct){ } k: (_|_){ // [eval] k: cannot range over e (found int, want list or struct): // ./in.cue:7:14 } e: (int){ int } comprehensionBinds: (struct){ a: (struct){ a: (_){ _ } } b: (struct){ a: (_){ _ } } } } -- out/compile -- --- in.cue { b: { for k, v in 〈1;a〉 { "\(〈1;k〉)": (〈1;v〉 + 1) } } a: { b: 1 c: 2 } x: { for k, v in 〈1;y〉 { "\(〈1;k〉)": 〈1;v〉 } } y: {} k: { for _, v in 〈1;e〉 { 〈1;v〉 } } e: int comprehensionBinds: { a: { for _, _ in [ 1, ] { a: _ } } b: { for _, _ in [ 1, ] { a: _ } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/iferror.txtar000066400000000000000000000210451474664451600246570ustar00rootroot00000000000000-- in.cue -- a: {b: 2, c: int} wrongConcreteType: { if a.b { 2 } } wrongType: { if a.c { 2 } } incomplete: { if a.d { 2 } } incomplete: { list: [1, 2, 3] for x in list if a.d { x } } // Issue #809 useDefault: { a: { x: *"foo" | string if x != _|_ { y: x } } issue809: { #A: { a: string b: *a | string } s: [Name=string]: #A & {a: Name} s: bar: _ foo: [ for _, a in s if a.b != _|_ {a}, ] } } issue1972: { err1: { #patchs: [] #patchs #someCondition: _ if #someCondition { } } err1: { someCondition: _ patchs: [...{}] patchs if someCondition { patchs: _ } } } -- out/compile -- --- in.cue { a: { b: 2 c: int } wrongConcreteType: { if 〈1;a〉.b { 2 } } wrongType: { if 〈1;a〉.c { 2 } } incomplete: { if 〈1;a〉.d { 2 } } incomplete: { list: [ 1, 2, 3, ] for _, x in 〈0;list〉 if 〈2;a〉.d { 〈1;x〉 } } useDefault: { a: { x: (*"foo"|string) if (〈0;x〉 != _|_(explicit error (_|_ literal) in source)) { y: 〈1;x〉 } } issue809: { #A: { a: string b: (*〈0;a〉|string) } s: { [string]: (〈1;#A〉 & { a: 〈1;-〉 }) } s: { bar: _ } foo: [ for _, a in 〈1;s〉 if (〈0;a〉.b != _|_(explicit error (_|_ literal) in source)) { 〈1;a〉 }, ] } } issue1972: { err1: { #patchs: [] 〈0;#patchs〉 #someCondition: _ if 〈0;#someCondition〉 {} } err1: { someCondition: _ patchs: [ ...{}, ] 〈0;patchs〉 if 〈0;someCondition〉 { patchs: _ } } } } -- out/eval/stats -- Leaks: 0 Freed: 43 Reused: 35 Allocs: 8 Retain: 14 Unifications: 33 Conjuncts: 66 Disjuncts: 57 -- out/evalalpha -- Errors: issue1972.err1: conflicting values [...{}] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): ./in.cue:61:8 ./in.cue:63:11 issue1972.err1.someCondition: field not allowed: ./in.cue:62:3 wrongConcreteType: cannot use 2 (type int) as type bool: ./in.cue:4:2 ./in.cue:1:8 wrongType: cannot use int (type int) as type bool: ./in.cue:10:2 ./in.cue:1:14 Result: (_|_){ // [eval] a: (struct){ b: (int){ 2 } c: (int){ int } } wrongConcreteType: (_|_){ // [eval] wrongConcreteType: cannot use 2 (type int) as type bool: // ./in.cue:4:2 // ./in.cue:1:8 } wrongType: (_|_){ // [eval] wrongType: cannot use int (type int) as type bool: // ./in.cue:10:2 // ./in.cue:1:14 } incomplete: (_|_){ // [incomplete] incomplete: undefined field: d: // ./in.cue:16:7 // incomplete: undefined field: d: // ./in.cue:23:21 list: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } } useDefault: (struct){ a: (struct){ x: (string){ |(*(string){ "foo" }, (string){ string }) } y: (string){ |(*(string){ "foo" }, (string){ string }) } } issue809: (struct){ #A: (#struct){ a: (string){ string } b: (string){ string } } s: (struct){ bar: (#struct){ a: (string){ "bar" } b: (string){ |(*(string){ "bar" }, (string){ string }) } } } foo: (#list){ 0: (#struct){ a: (string){ "bar" } b: (string){ |(*(string){ "bar" }, (string){ string }) } } } } } issue1972: (_|_){ // [eval] err1: (_|_){ // [eval] issue1972.err1: conflicting values [...{}] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): // ./in.cue:61:8 // ./in.cue:63:11 // issue1972.err1.someCondition: field not allowed: // ./in.cue:62:3 #patchs: (#list){ } #someCondition: (_){ _ } someCondition: (_|_){ // [eval] issue1972.err1.someCondition: field not allowed: // ./in.cue:62:3 } patchs: (_|_){ // [eval] issue1972.err1.patchs: field not allowed: // ./in.cue:63:3 // ./in.cue:66:4 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,9 @@ Errors: -issue1972.err1: conflicting values [] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): - ./in.cue:54:12 +issue1972.err1: conflicting values [...{}] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): ./in.cue:61:8 + ./in.cue:63:11 +issue1972.err1.someCondition: field not allowed: + ./in.cue:62:3 wrongConcreteType: cannot use 2 (type int) as type bool: ./in.cue:4:2 ./in.cue:1:8 @@ -8,8 +10,6 @@ wrongType: cannot use int (type int) as type bool: ./in.cue:10:2 ./in.cue:1:14 -issue1972.err1: invalid list index someCondition (type string): - ./in.cue:65:6 Result: (_|_){ @@ -66,17 +66,23 @@ issue1972: (_|_){ // [eval] err1: (_|_){ - // [eval] issue1972.err1: conflicting values [] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): - // ./in.cue:54:12 + // [eval] issue1972.err1: conflicting values [...{}] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): // ./in.cue:61:8 - // issue1972.err1: invalid list index someCondition (type string): - // ./in.cue:65:6 + // ./in.cue:63:11 + // issue1972.err1.someCondition: field not allowed: + // ./in.cue:62:3 #patchs: (#list){ } - someCondition: (_){ _ } - patchs: (list){ - } #someCondition: (_){ _ } + someCondition: (_|_){ + // [eval] issue1972.err1.someCondition: field not allowed: + // ./in.cue:62:3 + } + patchs: (_|_){ + // [eval] issue1972.err1.patchs: field not allowed: + // ./in.cue:63:3 + // ./in.cue:66:4 + } } } } -- diff/todo/p2 -- issue1972: "field not allowed" are somewhat correct (it is also a list), but are already covered by the other error message and should be elided. This may lead to a large number of errors otherwise. -- out/eval -- Errors: issue1972.err1: conflicting values [] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): ./in.cue:54:12 ./in.cue:61:8 wrongConcreteType: cannot use 2 (type int) as type bool: ./in.cue:4:2 ./in.cue:1:8 wrongType: cannot use int (type int) as type bool: ./in.cue:10:2 ./in.cue:1:14 issue1972.err1: invalid list index someCondition (type string): ./in.cue:65:6 Result: (_|_){ // [eval] a: (struct){ b: (int){ 2 } c: (int){ int } } wrongConcreteType: (_|_){ // [eval] wrongConcreteType: cannot use 2 (type int) as type bool: // ./in.cue:4:2 // ./in.cue:1:8 } wrongType: (_|_){ // [eval] wrongType: cannot use int (type int) as type bool: // ./in.cue:10:2 // ./in.cue:1:14 } incomplete: (_|_){ // [incomplete] incomplete: undefined field: d: // ./in.cue:16:7 // incomplete: undefined field: d: // ./in.cue:23:21 list: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } } useDefault: (struct){ a: (struct){ x: (string){ |(*(string){ "foo" }, (string){ string }) } y: (string){ |(*(string){ "foo" }, (string){ string }) } } issue809: (struct){ #A: (#struct){ a: (string){ string } b: (string){ string } } s: (struct){ bar: (#struct){ a: (string){ "bar" } b: (string){ |(*(string){ "bar" }, (string){ string }) } } } foo: (#list){ 0: (#struct){ a: (string){ "bar" } b: (string){ |(*(string){ "bar" }, (string){ string }) } } } } } issue1972: (_|_){ // [eval] err1: (_|_){ // [eval] issue1972.err1: conflicting values [] and {someCondition:_,patchs:[...{}],patchs,if someCondition {patchs:_}} (mismatched types list and struct): // ./in.cue:54:12 // ./in.cue:61:8 // issue1972.err1: invalid list index someCondition (type string): // ./in.cue:65:6 #patchs: (#list){ } someCondition: (_){ _ } patchs: (list){ } #someCondition: (_){ _ } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/incomplete.txtar000066400000000000000000000014111474664451600253410ustar00rootroot00000000000000-- in.cue -- cond: bool src: {} top: _ a: [ if cond {}] b: [for x in src.foo {}] c: {for x in top {}} -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 5 Allocs: 2 Retain: 0 Unifications: 7 Conjuncts: 7 Disjuncts: 7 -- out/eval -- (struct){ cond: (bool){ bool } src: (struct){ } top: (_){ _ } a: (_|_){ // [incomplete] a: incomplete bool: bool: // ./in.cue:1:7 } b: (_|_){ // [incomplete] b: undefined field: foo: // ./in.cue:5:18 } c: (_|_){ // [incomplete] c: cannot range over top (incomplete type _): // ./in.cue:6:14 } } -- out/compile -- --- in.cue { cond: bool src: {} top: _ a: [ if 〈1;cond〉 {}, ] b: [ for _, x in 〈1;src〉.foo {}, ] c: { for _, x in 〈1;top〉 {} } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue1732.txtar000066400000000000000000000376531474664451600246700ustar00rootroot00000000000000-- in.cue -- package config networkingv1: { metav1: { #LabelSelector: { matchLabels: {[string]: string} } } #NetworkPolicy: { spec: #NetworkPolicySpec } #NetworkPolicySpec: { ingress: [...#NetworkPolicyIngressRule] egress: [...#NetworkPolicyEgressRule] } #NetworkPolicyIngressRule: { from: [...#NetworkPolicyPeer] } #NetworkPolicyEgressRule: { to: [...#NetworkPolicyPeer] } #NetworkPolicyPeer: { namespaceSelector: null | metav1.#LabelSelector } } global_config: { #GlobalConfig: { auth0: { enabled: bool } } } common: { #SomeConfig: { enabled: bool if enabled { foo: string } } } foo: { #Values: { global: global_config.#GlobalConfig } } #Config: R={ tenant: id: string auth0: common.#SomeConfig & { enabled: bool if (enabled) { foo: "\(tenant.id)-value" } } charts: { "foo": foo.#Values & { global: R.global } } global: global_config.#GlobalConfig & { auth0: enabled: R.auth0.enabled } } #NetworkPolicy: networkingv1.#NetworkPolicy #Flux: R={ #Config charts: _ formatOutput: {...} _outputs: {...} for _chartName, _chartValues in charts { _outputs: "\(_chartName)": {} } _outputs: { for ns in ["ns"] { "\(ns)/network": #NetworkPolicy & { spec: { ingress: [ { from: [{ namespaceSelector: matchLabels: { tenant: R.tenant.id } }] }, ] egress: [ { to: [{ namespaceSelector: matchLabels: { tenant: R.tenant.id } }] }, ] } } } } for ns in ["ns"] { for k, v in _outputs { formatOutput: "\(k)": v } } } -- out/eval/stats -- Leaks: 3 Freed: 118 Reused: 103 Allocs: 18 Retain: 10 Unifications: 111 Conjuncts: 249 Disjuncts: 126 -- out/evalalpha -- (struct){ networkingv1: (struct){ metav1: (struct){ #LabelSelector: (#struct){ matchLabels: (#struct){ } } } #NetworkPolicy: (#struct){ spec: ~(networkingv1.#NetworkPolicySpec) } #NetworkPolicySpec: (#struct){ ingress: (list){ } egress: (list){ } } #NetworkPolicyIngressRule: (#struct){ from: (list){ } } #NetworkPolicyEgressRule: (#struct){ to: (list){ } } #NetworkPolicyPeer: (#struct){ namespaceSelector: ((null|struct)){ |((null){ null }, (#struct){ matchLabels: (#struct){ } }) } } } global_config: (struct){ #GlobalConfig: (#struct){ auth0: (#struct){ enabled: (bool){ bool } } } } common: (struct){ #SomeConfig: (_|_){ // [incomplete] common.#SomeConfig: incomplete bool: bool: // ./in.cue:41:12 enabled: (bool){ bool } } } foo: (struct){ #Values: (#struct){ global: ~(global_config.#GlobalConfig) } } #Config: (#struct){ tenant: (#struct){ id: (string){ string } } auth0: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: // ./in.cue:58:12 enabled: (bool){ bool } } charts: (#struct){ foo: (#struct){ global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: // ./in.cue:58:12 } } } } } global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: // ./in.cue:58:12 } } } } #NetworkPolicy: ~(networkingv1.#NetworkPolicy) #Flux: (#struct){ charts: (#struct){ foo: (#struct){ global: (#struct){ auth0: (#struct){ enabled: (bool){ bool } } } } } formatOutput: (#struct){ foo: (#struct){ } "ns/network": ~(#Flux._outputs(:config)."ns/network") } _outputs(:config): (#struct){ foo: (#struct){ } "ns/network": (#struct){ spec: (#struct){ ingress: (#list){ 0: (#struct){ from: (#list){ 0: (#struct){ namespaceSelector: (#struct){ matchLabels: (#struct){ tenant: (string){ string } } } } } } } egress: (#list){ 0: (#struct){ to: (#list){ 0: (#struct){ namespaceSelector: (#struct){ matchLabels: (#struct){ tenant: (string){ string } } } } } } } } } } tenant: (#struct){ id: (string){ string } } auth0: (_|_){ // [incomplete] #Flux.auth0: incomplete bool: bool: // ./in.cue:58:12 enabled: (bool){ bool } } global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Flux.auth0: incomplete bool: bool: // ./in.cue:58:12 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -7,12 +7,7 @@ } } #NetworkPolicy: (#struct){ - spec: (#struct){ - ingress: (list){ - } - egress: (list){ - } - } + spec: ~(networkingv1.#NetworkPolicySpec) } #NetworkPolicySpec: (#struct){ ingress: (list){ @@ -51,11 +46,7 @@ } foo: (struct){ #Values: (#struct){ - global: (#struct){ - auth0: (#struct){ - enabled: (bool){ bool } - } - } + global: ~(global_config.#GlobalConfig) } } #Config: (#struct){ @@ -64,7 +55,7 @@ } auth0: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: - // ./in.cue:41:12 + // ./in.cue:58:12 enabled: (bool){ bool } } charts: (#struct){ @@ -73,7 +64,7 @@ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: - // ./in.cue:41:12 + // ./in.cue:58:12 } } } @@ -83,45 +74,19 @@ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: - // ./in.cue:41:12 - } - } - } - } - #NetworkPolicy: (#struct){ - spec: (#struct){ - ingress: (list){ - } - egress: (list){ - } - } - } + // ./in.cue:58:12 + } + } + } + } + #NetworkPolicy: ~(networkingv1.#NetworkPolicy) #Flux: (#struct){ - tenant: (#struct){ - id: (string){ string } - } - auth0: (_|_){ - // [incomplete] #Flux.auth0: incomplete bool: bool: - // ./in.cue:41:12 - enabled: (bool){ bool } - } - charts: (#struct){ - foo: (#struct){ - global: (#struct){ - auth0: (#struct){ - enabled: (_|_){ - // [incomplete] #Flux.auth0: incomplete bool: bool: - // ./in.cue:41:12 - } - } - } - } - } - global: (#struct){ - auth0: (#struct){ - enabled: (_|_){ - // [incomplete] #Flux.auth0: incomplete bool: bool: - // ./in.cue:41:12 + charts: (#struct){ + foo: (#struct){ + global: (#struct){ + auth0: (#struct){ + enabled: (bool){ bool } + } } } } @@ -128,36 +93,7 @@ formatOutput: (#struct){ foo: (#struct){ } - "ns/network": (#struct){ - spec: (#struct){ - ingress: (#list){ - 0: (#struct){ - from: (#list){ - 0: (#struct){ - namespaceSelector: (#struct){ - matchLabels: (#struct){ - tenant: (string){ string } - } - } - } - } - } - } - egress: (#list){ - 0: (#struct){ - to: (#list){ - 0: (#struct){ - namespaceSelector: (#struct){ - matchLabels: (#struct){ - tenant: (string){ string } - } - } - } - } - } - } - } - } + "ns/network": ~(#Flux._outputs(:config)."ns/network") } _outputs(:config): (#struct){ foo: (#struct){ @@ -193,5 +129,21 @@ } } } + tenant: (#struct){ + id: (string){ string } + } + auth0: (_|_){ + // [incomplete] #Flux.auth0: incomplete bool: bool: + // ./in.cue:58:12 + enabled: (bool){ bool } + } + global: (#struct){ + auth0: (#struct){ + enabled: (_|_){ + // [incomplete] #Flux.auth0: incomplete bool: bool: + // ./in.cue:58:12 + } + } + } } } -- diff/todo/p2 -- #Flux.charts.foo.global.auth0.enabled: missing error The error messages should say which expression was incomplete!!! -- out/eval -- (struct){ networkingv1: (struct){ metav1: (struct){ #LabelSelector: (#struct){ matchLabels: (#struct){ } } } #NetworkPolicy: (#struct){ spec: (#struct){ ingress: (list){ } egress: (list){ } } } #NetworkPolicySpec: (#struct){ ingress: (list){ } egress: (list){ } } #NetworkPolicyIngressRule: (#struct){ from: (list){ } } #NetworkPolicyEgressRule: (#struct){ to: (list){ } } #NetworkPolicyPeer: (#struct){ namespaceSelector: ((null|struct)){ |((null){ null }, (#struct){ matchLabels: (#struct){ } }) } } } global_config: (struct){ #GlobalConfig: (#struct){ auth0: (#struct){ enabled: (bool){ bool } } } } common: (struct){ #SomeConfig: (_|_){ // [incomplete] common.#SomeConfig: incomplete bool: bool: // ./in.cue:41:12 enabled: (bool){ bool } } } foo: (struct){ #Values: (#struct){ global: (#struct){ auth0: (#struct){ enabled: (bool){ bool } } } } } #Config: (#struct){ tenant: (#struct){ id: (string){ string } } auth0: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: // ./in.cue:41:12 enabled: (bool){ bool } } charts: (#struct){ foo: (#struct){ global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: // ./in.cue:41:12 } } } } } global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Config.auth0: incomplete bool: bool: // ./in.cue:41:12 } } } } #NetworkPolicy: (#struct){ spec: (#struct){ ingress: (list){ } egress: (list){ } } } #Flux: (#struct){ tenant: (#struct){ id: (string){ string } } auth0: (_|_){ // [incomplete] #Flux.auth0: incomplete bool: bool: // ./in.cue:41:12 enabled: (bool){ bool } } charts: (#struct){ foo: (#struct){ global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Flux.auth0: incomplete bool: bool: // ./in.cue:41:12 } } } } } global: (#struct){ auth0: (#struct){ enabled: (_|_){ // [incomplete] #Flux.auth0: incomplete bool: bool: // ./in.cue:41:12 } } } formatOutput: (#struct){ foo: (#struct){ } "ns/network": (#struct){ spec: (#struct){ ingress: (#list){ 0: (#struct){ from: (#list){ 0: (#struct){ namespaceSelector: (#struct){ matchLabels: (#struct){ tenant: (string){ string } } } } } } } egress: (#list){ 0: (#struct){ to: (#list){ 0: (#struct){ namespaceSelector: (#struct){ matchLabels: (#struct){ tenant: (string){ string } } } } } } } } } } _outputs(:config): (#struct){ foo: (#struct){ } "ns/network": (#struct){ spec: (#struct){ ingress: (#list){ 0: (#struct){ from: (#list){ 0: (#struct){ namespaceSelector: (#struct){ matchLabels: (#struct){ tenant: (string){ string } } } } } } } egress: (#list){ 0: (#struct){ to: (#list){ 0: (#struct){ namespaceSelector: (#struct){ matchLabels: (#struct){ tenant: (string){ string } } } } } } } } } } } } -- out/compile -- --- in.cue { networkingv1: { metav1: { #LabelSelector: { matchLabels: { [string]: string } } } #NetworkPolicy: { spec: 〈1;#NetworkPolicySpec〉 } #NetworkPolicySpec: { ingress: [ ...〈2;#NetworkPolicyIngressRule〉, ] egress: [ ...〈2;#NetworkPolicyEgressRule〉, ] } #NetworkPolicyIngressRule: { from: [ ...〈2;#NetworkPolicyPeer〉, ] } #NetworkPolicyEgressRule: { to: [ ...〈2;#NetworkPolicyPeer〉, ] } #NetworkPolicyPeer: { namespaceSelector: (null|〈1;metav1〉.#LabelSelector) } } global_config: { #GlobalConfig: { auth0: { enabled: bool } } } common: { #SomeConfig: { enabled: bool if 〈0;enabled〉 { foo: string } } } foo: { #Values: { global: 〈2;global_config〉.#GlobalConfig } } #Config: { tenant: { id: string } auth0: (〈1;common〉.#SomeConfig & { enabled: bool if 〈0;enabled〉 { foo: "\(〈2;tenant〉.id)-value" } }) charts: { foo: (〈2;foo〉.#Values & { global: 〈3〉.global }) } global: (〈1;global_config〉.#GlobalConfig & { auth0: { enabled: 〈3〉.auth0.enabled } }) } #NetworkPolicy: 〈0;networkingv1〉.#NetworkPolicy #Flux: { 〈1;#Config〉 charts: _ formatOutput: { ... } _outputs: { ... } for _chartName, _chartValues in 〈0;charts〉 { _outputs: { "\(〈2;_chartName〉)": {} } } _outputs: { for _, ns in [ "ns", ] { "\(〈1;ns〉)/network": (〈4;#NetworkPolicy〉 & { spec: { ingress: [ { from: [ { namespaceSelector: { matchLabels: { tenant: 〈12〉.tenant.id } } }, ] }, ] egress: [ { to: [ { namespaceSelector: { matchLabels: { tenant: 〈12〉.tenant.id } } }, ] }, ] } }) } } for _, ns in [ "ns", ] { for k, v in 〈2;_outputs〉 { formatOutput: { "\(〈2;k〉)": 〈2;v〉 } } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue2171.txtar000066400000000000000000000007371474664451600246570ustar00rootroot00000000000000// Sometimes an arc should not "Finalize" itself. See Issue #2171 in eval.go. -- in.cue -- package x do: { hello: { } } for k, v in do {do: (k): v} -- out/compile -- --- in.cue { do: { hello: {} } for k, v in 〈0;do〉 { do: { 〈2;k〉: 〈2;v〉 } } } -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 0 Allocs: 3 Retain: 0 Unifications: 3 Conjuncts: 5 Disjuncts: 3 -- out/eval -- (struct){ do: (struct){ hello: (struct){ } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue2481.txtar000066400000000000000000000064351474664451600246640ustar00rootroot00000000000000 -- in.cue -- // Mixing struct fields and embedded scalars should error. Using comprehensions // this follows a different path which may miss the error. // TODO: fix out: { for k in keys { if values[k] != _|_ { val: k if val != _|_ { k } } } } // multiple lets are mapped to the same location and will conflict. This is // fine, though, as lets do not represent a single data field. This should // therefore not error. // TODO: fix multiLets: { for k in keys { if values[k] != _|_ { let val = k if val != _|_ { k } } } } keys: [ // order matters "a", "b", ] values: { // order does not matter "b": "member" "c": "foo" } full: { out: { // changing this to a list of the keys "fixes" things, i.e. this comprehension is required for k, _ in #github_team_membership { // Remove this comprehension to trigger a different type of cycle error if ( values[k] != _|_ ) { // This let is also required let val = values[k] if val != null && ((val & string) != _|_) { (k): val } } } } #github_team_membership: { team_id: string role: string } values: { "role": "member" "username": "foo" } } -- out/eval/stats -- Leaks: 3 Freed: 23 Reused: 17 Allocs: 9 Retain: 58 Unifications: 26 Conjuncts: 50 Disjuncts: 56 -- out/eval -- Errors: out: cannot combine regular field "val" with "b": ./in.cue:33:2 Result: (_|_){ // [eval] out: (_|_){ // [eval] out: cannot combine regular field "val" with "b": // ./in.cue:33:2 val: (string){ "b" } } multiLets: (string){ "b" let val#1multi = 〈2;k〉 } keys: (#list){ 0: (string){ "a" } 1: (string){ "b" } } values: (struct){ b: (string){ "member" } c: (string){ "foo" } } full: (struct){ out: (struct){ let val#2multi = 〈4;values〉[〈2;k〉] role: (string){ "member" } } #github_team_membership: (#struct){ team_id: (string){ string } role: (string){ string } } values: (struct){ role: (string){ "member" } username: (string){ "foo" } } } } -- out/compile -- --- in.cue { out: { for _, k in 〈1;keys〉 { if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { val: 〈2;k〉 if (〈0;val〉 != _|_(explicit error (_|_ literal) in source)) { 〈3;k〉 } } } } multiLets: { for _, k in 〈1;keys〉 { if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { let val#1multi = 〈2;k〉 if (〈0;let val#1〉 != _|_(explicit error (_|_ literal) in source)) { 〈3;k〉 } } } } keys: [ "a", "b", ] values: { b: "member" c: "foo" } full: { out: { for k, _ in 〈1;#github_team_membership〉 { if (〈3;values〉[〈1;k〉] != _|_(explicit error (_|_ literal) in source)) { let val#2multi = 〈4;values〉[〈2;k〉] if ((〈0;let val#2〉 != null) && ((〈0;let val#2〉 & string) != _|_(explicit error (_|_ literal) in source))) { 〈3;k〉: 〈1;let val#2〉 } } } } #github_team_membership: { team_id: string role: string } values: { role: "member" username: "foo" } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue287.txtar000066400000000000000000000011511474664451600245740ustar00rootroot00000000000000-- in.cue -- if #E["x"] != _|_ { #E: y: true } if #E["y"] != _|_ { z: true } #E: [_]: bool #E: x: true -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 1 Allocs: 4 Retain: 2 Unifications: 5 Conjuncts: 7 Disjuncts: 5 -- out/eval -- (struct){ #E: (#struct){ y: (bool){ true } x: (bool){ true } } z: (bool){ true } } -- out/compile -- --- in.cue { if (〈0;#E〉["x"] != _|_(explicit error (_|_ literal) in source)) { #E: { y: true } } if (〈0;#E〉["y"] != _|_(explicit error (_|_ literal) in source)) { z: true } #E: { [_]: bool } #E: { x: true } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue293.txtar000066400000000000000000000067511474664451600246040ustar00rootroot00000000000000 -- in.cue -- #T: { if true { // We'd like to restrict the possible members of x in this case, // but this doesn't work. x: close({ f1: int }) } x: _ } z: #T & { x: { f1: 99 f2: "i want to disallow this" } } t: #C #C: { if true { p: _ } } t: p: "foo" -- variant1.cue -- #V1: { x: close({ f1: int }) x: f2: 2 } -- out/eval/stats -- Leaks: 3 Freed: 16 Reused: 12 Allocs: 7 Retain: 4 Unifications: 19 Conjuncts: 33 Disjuncts: 20 -- out/evalalpha -- Errors: z.x.f2: field not allowed: ./in.cue:5:6 ./in.cue:14:3 #V1.x.f2: field not allowed: ./variant1.cue:2:5 ./variant1.cue:3:5 Result: (_|_){ // [eval] #T: (#struct){ x: (#struct){ f1: (int){ int } } } z: (_|_){ // [eval] x: (_|_){ // [eval] f1: (int){ 99 } f2: (_|_){ // [eval] z.x.f2: field not allowed: // ./in.cue:5:6 // ./in.cue:14:3 } } } t: (#struct){ p: (string){ "foo" } } #C: (#struct){ p: (_){ _ } } #V1: (_|_){ // [eval] x: (_|_){ // [eval] f2: (_|_){ // [eval] #V1.x.f2: field not allowed: // ./variant1.cue:2:5 // ./variant1.cue:3:5 } f1: (int){ int } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,12 +1,10 @@ Errors: -#V1.x.f2: field not allowed: - ./variant1.cue:2:11 - ./variant1.cue:3:5 z.x.f2: field not allowed: - ./in.cue:2:2 - ./in.cue:5:12 - ./in.cue:11:4 + ./in.cue:5:6 ./in.cue:14:3 +#V1.x.f2: field not allowed: + ./variant1.cue:2:5 + ./variant1.cue:3:5 Result: (_|_){ @@ -23,9 +21,7 @@ f1: (int){ 99 } f2: (_|_){ // [eval] z.x.f2: field not allowed: - // ./in.cue:2:2 - // ./in.cue:5:12 - // ./in.cue:11:4 + // ./in.cue:5:6 // ./in.cue:14:3 } } @@ -40,12 +36,12 @@ // [eval] x: (_|_){ // [eval] - f1: (int){ int } f2: (_|_){ // [eval] #V1.x.f2: field not allowed: - // ./variant1.cue:2:11 + // ./variant1.cue:2:5 // ./variant1.cue:3:5 } + f1: (int){ int } } } } -- diff/todo/p2 -- Missing positions -- diff/todo/p3 -- Reordering -- out/eval -- Errors: #V1.x.f2: field not allowed: ./variant1.cue:2:11 ./variant1.cue:3:5 z.x.f2: field not allowed: ./in.cue:2:2 ./in.cue:5:12 ./in.cue:11:4 ./in.cue:14:3 Result: (_|_){ // [eval] #T: (#struct){ x: (#struct){ f1: (int){ int } } } z: (_|_){ // [eval] x: (_|_){ // [eval] f1: (int){ 99 } f2: (_|_){ // [eval] z.x.f2: field not allowed: // ./in.cue:2:2 // ./in.cue:5:12 // ./in.cue:11:4 // ./in.cue:14:3 } } } t: (#struct){ p: (string){ "foo" } } #C: (#struct){ p: (_){ _ } } #V1: (_|_){ // [eval] x: (_|_){ // [eval] f1: (int){ int } f2: (_|_){ // [eval] #V1.x.f2: field not allowed: // ./variant1.cue:2:11 // ./variant1.cue:3:5 } } } } -- out/compile -- --- in.cue { #T: { if true { x: close({ f1: int }) } x: _ } z: (〈0;#T〉 & { x: { f1: 99 f2: "i want to disallow this" } }) t: 〈0;#C〉 #C: { if true { p: _ } } t: { p: "foo" } } --- variant1.cue { #V1: { x: close({ f1: int }) x: { f2: 2 } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue436.txtar000066400000000000000000000022121474664451600245670ustar00rootroot00000000000000-- in.cue -- #a: { val: string result: string } a: #a & { val: *"default" | string result: *"not-matched" | string if (val == "match") { result: "matched" } } match: a & { val: "match" } not: a & { val: "other" } -- out/eval/stats -- Leaks: 0 Freed: 25 Reused: 20 Allocs: 5 Retain: 0 Unifications: 13 Conjuncts: 44 Disjuncts: 25 -- out/eval -- (struct){ #a: (#struct){ val: (string){ string } result: (string){ string } } a: (#struct){ val: (string){ |(*(string){ "default" }, (string){ string }) } result: (string){ |(*(string){ "not-matched" }, (string){ string }) } } match: (#struct){ val: (string){ "match" } result: (string){ "matched" } } not: (#struct){ val: (string){ "other" } result: (string){ |(*(string){ "not-matched" }, (string){ string }) } } } -- out/compile -- --- in.cue { #a: { val: string result: string } a: (〈0;#a〉 & { val: (*"default"|string) result: (*"not-matched"|string) if (〈0;val〉 == "match") { result: "matched" } }) match: (〈0;a〉 & { val: "match" }) not: (〈0;a〉 & { val: "other" }) } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue507.txtar000066400000000000000000000023201474664451600245660ustar00rootroot00000000000000-- in.cue -- package x somelist: [...string] | *[] // Works just fine foo: [ for e in somelist { "hello foo: \(e)" }, ] otherlist: ["something"] // Works fine as well z: [ for e in otherlist { "hello z: \(e)" }, ] extlist: [...string] | *["something"] bar: [ for e in extlist { "hello bar: \(e)" }, ] -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 10 Allocs: 5 Retain: 0 Unifications: 11 Conjuncts: 17 Disjuncts: 15 -- out/eval -- (struct){ somelist: (list){ |(*(#list){ }, (list){ }) } foo: (#list){ } otherlist: (#list){ 0: (string){ "something" } } z: (#list){ 0: (string){ "hello z: something" } } extlist: (list){ |(*(#list){ 0: (string){ "something" } }, (list){ }) } bar: (#list){ 0: (string){ "hello bar: something" } } } -- out/compile -- --- in.cue { somelist: ([ ...string, ]|*[]) foo: [ for _, e in 〈1;somelist〉 { "hello foo: \(〈1;e〉)" }, ] otherlist: [ "something", ] z: [ for _, e in 〈1;otherlist〉 { "hello z: \(〈1;e〉)" }, ] extlist: ([ ...string, ]|*[ "something", ]) bar: [ for _, e in 〈1;extlist〉 { "hello bar: \(〈1;e〉)" }, ] } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue837.txtar000066400000000000000000000346651474664451600246150ustar00rootroot00000000000000-- in.cue -- #DeploymentManifest: #Manifest & {ref: kind: "deployment"} #Manifest: { ref: #ManifestRef description: #KumoriKinds[ref.kind] } #ManifestRef: kind: #KindsNames #KindsNames: "service" | "deployment" #KumoriKinds: deployment: #Deployment #KumoriKinds: [string]: {...} #DoDeploy: { _params: manifest: #DeploymentManifest deployment: { description: { let dep = _params.manifest.description service: (#Configure & { _params: hsize: dep.hsize }).service } } } #Configure: { $p=_params: { hsize: [string]: #RoleSize } service: { description: { let configed = (#RelabelService & { _params: { hsize: $p.hsize } role: "admin" }).out role: configed.role } } } #RelabelService: { $p=_params: { hsize: #RoleSize } out: { labstr: $p.label } } #RoleSize: { $_instances: >=0 | *1 } #Deployment: { service: #ServiceManifest hsize: [service.description.#roles]: #RoleSize } #ServiceManifest: #Manifest & {ref: kind: "service"} -- out/evalalpha/stats -- Leaks: 123 Freed: 10 Reused: 9 Allocs: 124 Retain: 0 Unifications: 95 Conjuncts: 563 Disjuncts: 30 -- out/evalalpha -- Errors: #Configure.service.description.role: undefined field: role: ./in.cue:40:19 #DoDeploy.deployment.description.service.description.role: undefined field: role: ./in.cue:40:19 #RelabelService.out.labstr: undefined field: label: ./in.cue:51:14 Result: (_|_){ // [eval] #DeploymentManifest: (#struct){ ref: (#struct){ kind: (string){ "deployment" } } description: ~(#KumoriKinds.deployment) } #Manifest: (#struct){ ref: ~(#ManifestRef) description: (_|_){ // [incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string): // ./in.cue:5:15 } } #ManifestRef: (#struct){ kind: (string){ |((string){ "service" }, (string){ "deployment" }) } } #KindsNames: (string){ |((string){ "service" }, (string){ "deployment" }) } #KumoriKinds: (#struct){ deployment: (#struct){ service: ~(#ServiceManifest) hsize: (_|_){ // [incomplete] #ServiceManifest.description: undefined field: service: // ./in.cue:5:28 } } } #DoDeploy: (_|_){ // [eval] _params: (#struct){ manifest: ~(#DeploymentManifest) } deployment: (_|_){ // [eval] description: (_|_){ // [eval] let dep#1 = ~(#KumoriKinds.deployment) service: (_|_){ // [eval] description: (_|_){ // [eval] let configed#2 = (_|_){ // [eval] labstr: (_|_){ // [eval] #DoDeploy.deployment.description.service.description.configed.labstr: undefined field: label: // ./in.cue:51:14 } } role: (_|_){ // [eval] #DoDeploy.deployment.description.service.description.role: undefined field: role: // ./in.cue:40:19 } } } } } } #Configure: (_|_){ // [eval] _params: (#struct){ hsize: (#struct){ } } service: (_|_){ // [eval] description: (_|_){ // [eval] let configed#2 = (_|_){ // [eval] labstr: (_|_){ // [eval] #Configure.service.description.configed.labstr: undefined field: label: // ./in.cue:51:14 } } role: (_|_){ // [eval] #Configure.service.description.role: undefined field: role: // ./in.cue:40:19 } } } } #RelabelService: (_|_){ // [eval] _params: (#struct){ hsize: ~(#RoleSize) } out: (_|_){ // [eval] labstr: (_|_){ // [eval] #RelabelService.out.labstr: undefined field: label: // ./in.cue:51:14 } } } #RoleSize: (#struct){ $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) } } #Deployment: (#struct){ service: ~(#ServiceManifest) hsize: (_|_){ // [incomplete] #ServiceManifest.description: undefined field: service: // ./in.cue:5:28 } } #ServiceManifest: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #ServiceManifest.description: undefined field: service: // ./in.cue:5:28 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -13,24 +13,10 @@ ref: (#struct){ kind: (string){ "deployment" } } - description: (#struct){ - service: (#struct){ - ref: (#struct){ - kind: (string){ "service" } - } - description: (_|_){ - // [incomplete] #DeploymentManifest.description.service.description: undefined field: service: - // ./in.cue:5:28 - } - } - hsize: (#struct){ - } - } + description: ~(#KumoriKinds.deployment) } #Manifest: (#struct){ - ref: (#struct){ - kind: (string){ |((string){ "service" }, (string){ "deployment" }) } - } + ref: ~(#ManifestRef) description: (_|_){ // [incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string): // ./in.cue:5:15 @@ -42,16 +28,10 @@ #KindsNames: (string){ |((string){ "service" }, (string){ "deployment" }) } #KumoriKinds: (#struct){ deployment: (#struct){ - service: (#struct){ - ref: (#struct){ - kind: (string){ "service" } - } - description: (_|_){ - // [incomplete] #KumoriKinds.deployment.service.description: undefined field: service: - // ./in.cue:5:28 - } - } - hsize: (#struct){ + service: ~(#ServiceManifest) + hsize: (_|_){ + // [incomplete] #ServiceManifest.description: undefined field: service: + // ./in.cue:5:28 } } } @@ -58,42 +38,13 @@ #DoDeploy: (_|_){ // [eval] _params: (#struct){ - manifest: (#struct){ - ref: (#struct){ - kind: (string){ "deployment" } - } - description: (#struct){ - service: (#struct){ - ref: (#struct){ - kind: (string){ "service" } - } - description: (_|_){ - // [incomplete] #DoDeploy._params.manifest.description.service.description: undefined field: service: - // ./in.cue:5:28 - } - } - hsize: (#struct){ - } - } - } + manifest: ~(#DeploymentManifest) } deployment: (_|_){ // [eval] description: (_|_){ // [eval] - let dep#1 = (#struct){ - service: (#struct){ - ref: (#struct){ - kind: (string){ "service" } - } - description: (_|_){ - // [incomplete] #DoDeploy.deployment.description.dep.service.description: undefined field: service: - // ./in.cue:5:28 - } - } - hsize: (#struct){ - } - } + let dep#1 = ~(#KumoriKinds.deployment) service: (_|_){ // [eval] description: (_|_){ @@ -141,9 +92,7 @@ #RelabelService: (_|_){ // [eval] _params: (#struct){ - hsize: (#struct){ - $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) } - } + hsize: ~(#RoleSize) } out: (_|_){ // [eval] @@ -157,16 +106,10 @@ $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) } } #Deployment: (#struct){ - service: (#struct){ - ref: (#struct){ - kind: (string){ "service" } - } - description: (_|_){ - // [incomplete] #Deployment.service.description: undefined field: service: - // ./in.cue:5:28 - } - } - hsize: (#struct){ + service: ~(#ServiceManifest) + hsize: (_|_){ + // [incomplete] #ServiceManifest.description: undefined field: service: + // ./in.cue:5:28 } } #ServiceManifest: (#struct){ -- out/eval/stats -- Leaks: 16 Freed: 117 Reused: 108 Allocs: 25 Retain: 53 Unifications: 107 Conjuncts: 243 Disjuncts: 170 -- out/eval -- Errors: #Configure.service.description.role: undefined field: role: ./in.cue:40:19 #DoDeploy.deployment.description.service.description.role: undefined field: role: ./in.cue:40:19 #RelabelService.out.labstr: undefined field: label: ./in.cue:51:14 Result: (_|_){ // [eval] #DeploymentManifest: (#struct){ ref: (#struct){ kind: (string){ "deployment" } } description: (#struct){ service: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #DeploymentManifest.description.service.description: undefined field: service: // ./in.cue:5:28 } } hsize: (#struct){ } } } #Manifest: (#struct){ ref: (#struct){ kind: (string){ |((string){ "service" }, (string){ "deployment" }) } } description: (_|_){ // [incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string): // ./in.cue:5:15 } } #ManifestRef: (#struct){ kind: (string){ |((string){ "service" }, (string){ "deployment" }) } } #KindsNames: (string){ |((string){ "service" }, (string){ "deployment" }) } #KumoriKinds: (#struct){ deployment: (#struct){ service: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #KumoriKinds.deployment.service.description: undefined field: service: // ./in.cue:5:28 } } hsize: (#struct){ } } } #DoDeploy: (_|_){ // [eval] _params: (#struct){ manifest: (#struct){ ref: (#struct){ kind: (string){ "deployment" } } description: (#struct){ service: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #DoDeploy._params.manifest.description.service.description: undefined field: service: // ./in.cue:5:28 } } hsize: (#struct){ } } } } deployment: (_|_){ // [eval] description: (_|_){ // [eval] let dep#1 = (#struct){ service: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #DoDeploy.deployment.description.dep.service.description: undefined field: service: // ./in.cue:5:28 } } hsize: (#struct){ } } service: (_|_){ // [eval] description: (_|_){ // [eval] let configed#2 = (_|_){ // [eval] labstr: (_|_){ // [eval] #DoDeploy.deployment.description.service.description.configed.labstr: undefined field: label: // ./in.cue:51:14 } } role: (_|_){ // [eval] #DoDeploy.deployment.description.service.description.role: undefined field: role: // ./in.cue:40:19 } } } } } } #Configure: (_|_){ // [eval] _params: (#struct){ hsize: (#struct){ } } service: (_|_){ // [eval] description: (_|_){ // [eval] let configed#2 = (_|_){ // [eval] labstr: (_|_){ // [eval] #Configure.service.description.configed.labstr: undefined field: label: // ./in.cue:51:14 } } role: (_|_){ // [eval] #Configure.service.description.role: undefined field: role: // ./in.cue:40:19 } } } } #RelabelService: (_|_){ // [eval] _params: (#struct){ hsize: (#struct){ $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) } } } out: (_|_){ // [eval] labstr: (_|_){ // [eval] #RelabelService.out.labstr: undefined field: label: // ./in.cue:51:14 } } } #RoleSize: (#struct){ $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) } } #Deployment: (#struct){ service: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #Deployment.service.description: undefined field: service: // ./in.cue:5:28 } } hsize: (#struct){ } } #ServiceManifest: (#struct){ ref: (#struct){ kind: (string){ "service" } } description: (_|_){ // [incomplete] #ServiceManifest.description: undefined field: service: // ./in.cue:5:28 } } } -- diff/todo/p2 -- Some incorrect error messages. The newly introduced error messages for hsize seem to be correct, though. Error paths seem wrong as a result of structure sharing. Error path now selects into let. This is probably okay, and to some extent is clearer. -- out/compile -- --- in.cue { #DeploymentManifest: (〈0;#Manifest〉 & { ref: { kind: "deployment" } }) #Manifest: { ref: 〈1;#ManifestRef〉 description: 〈1;#KumoriKinds〉[〈0;ref〉.kind] } #ManifestRef: { kind: 〈1;#KindsNames〉 } #KindsNames: ("service"|"deployment") #KumoriKinds: { deployment: 〈1;#Deployment〉 } #KumoriKinds: { [string]: { ... } } #DoDeploy: { _params: { manifest: 〈2;#DeploymentManifest〉 } deployment: { description: { let dep#1 = 〈2;_params〉.manifest.description service: (〈3;#Configure〉 & { _params: { hsize: 〈2;let dep#1〉.hsize } }).service } } } #Configure: { _params: { hsize: { [string]: 〈3;#RoleSize〉 } } service: { description: { let configed#2 = (〈3;#RelabelService〉 & { _params: { hsize: 〈4;_params〉.hsize } role: "admin" }).out role: 〈0;let configed#2〉.role } } } #RelabelService: { _params: { hsize: 〈2;#RoleSize〉 } out: { labstr: 〈1;_params〉.label } } #RoleSize: { $_instances: (>=0|*1) } #Deployment: { service: 〈1;#ServiceManifest〉 hsize: { [〈1;service〉.description.#roles]: 〈2;#RoleSize〉 } } #ServiceManifest: (〈0;#Manifest〉 & { ref: { kind: "service" } }) } cue-lang-cue-db9cc73/cue/testdata/comprehensions/issue843.txtar000066400000000000000000000113261474664451600245770ustar00rootroot00000000000000-- in.cue -- package main import "list" #d1: { as: [...string] #c: [ #f1 & { "as": list.Concat([["go"], as]) }, ] } #d2: { p: *"." | string #c: [ #f2 & { from: #d1 & { as: [p] } }, ] } #c1: { #c: [...#o] _ ... } #o: #f1 | #f2 #f1: { do: "f1" as: [...string] } #f2: { do: "f2" from: #c1 } -- out/eval/stats -- Leaks: 0 Freed: 73 Reused: 58 Allocs: 15 Retain: 7 Unifications: 57 Conjuncts: 138 Disjuncts: 80 -- out/evalalpha -- (struct){ #d1: (#struct){ as: (list){ } #c: (#list){ 0: (#struct){ as: (#list){ 0: (string){ "go" } } do: (string){ "f1" } } } } #d2: (#struct){ p: (string){ |(*(string){ "." }, (string){ string }) } #c: (#list){ 0: (#struct){ from: (#struct){ as: (#list){ 0: (string){ |(*(string){ "." }, (string){ string }) } } #c: (#list){ 0: (#struct){ as: (#list){ 0: (string){ "go" } 1: (string){ |(*(string){ "." }, (string){ string }) } } do: (string){ "f1" } } } } do: (string){ "f2" } } } } #c1: (_){ _ #c: (list){ } } #o: (#struct){ |((#struct){ do: (string){ "f1" } as: (list){ } }, (#struct){ do: (string){ "f2" } from: ~(#c1) }) } #f1: (#struct){ do: (string){ "f1" } as: (list){ } } #f2: (#struct){ do: (string){ "f2" } from: ~(#c1) } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,10 +4,10 @@ } #c: (#list){ 0: (#struct){ - do: (string){ "f1" } as: (#list){ 0: (string){ "go" } } + do: (string){ "f1" } } } } @@ -15,21 +15,21 @@ p: (string){ |(*(string){ "." }, (string){ string }) } #c: (#list){ 0: (#struct){ - do: (string){ "f2" } from: (#struct){ + as: (#list){ + 0: (string){ |(*(string){ "." }, (string){ string }) } + } #c: (#list){ 0: (#struct){ - do: (string){ "f1" } as: (#list){ 0: (string){ "go" } 1: (string){ |(*(string){ "." }, (string){ string }) } } + do: (string){ "f1" } } } - as: (#list){ - 0: (string){ |(*(string){ "." }, (string){ string }) } - } - } + } + do: (string){ "f2" } } } } @@ -44,11 +44,7 @@ } }, (#struct){ do: (string){ "f2" } - from: (_){ - _ - #c: (list){ - } - } + from: ~(#c1) }) } #f1: (#struct){ do: (string){ "f1" } @@ -57,10 +53,6 @@ } #f2: (#struct){ do: (string){ "f2" } - from: (_){ - _ - #c: (list){ - } - } + from: ~(#c1) } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ #d1: (#struct){ as: (list){ } #c: (#list){ 0: (#struct){ do: (string){ "f1" } as: (#list){ 0: (string){ "go" } } } } } #d2: (#struct){ p: (string){ |(*(string){ "." }, (string){ string }) } #c: (#list){ 0: (#struct){ do: (string){ "f2" } from: (#struct){ #c: (#list){ 0: (#struct){ do: (string){ "f1" } as: (#list){ 0: (string){ "go" } 1: (string){ |(*(string){ "." }, (string){ string }) } } } } as: (#list){ 0: (string){ |(*(string){ "." }, (string){ string }) } } } } } } #c1: (_){ _ #c: (list){ } } #o: (#struct){ |((#struct){ do: (string){ "f1" } as: (list){ } }, (#struct){ do: (string){ "f2" } from: (_){ _ #c: (list){ } } }) } #f1: (#struct){ do: (string){ "f1" } as: (list){ } } #f2: (#struct){ do: (string){ "f2" } from: (_){ _ #c: (list){ } } } } -- out/compile -- --- in.cue { #d1: { as: [ ...string, ] #c: [ (〈2;#f1〉 & { as: 〈import;list〉.Concat([ [ "go", ], 〈3;as〉, ]) }), ] } #d2: { p: (*"."|string) #c: [ (〈2;#f2〉 & { from: (〈3;#d1〉 & { as: [ 〈4;p〉, ] }) }), ] } #c1: { #c: [ ...〈2;#o〉, ] _ ... } #o: (〈0;#f1〉|〈0;#f2〉) #f1: { do: "f1" as: [ ...string, ] } #f2: { do: "f2" from: 〈1;#c1〉 } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/lists.txtar000066400000000000000000000014651474664451600243510ustar00rootroot00000000000000-- in.cue -- a: [{a: 1}, {b: 2 & 3}] b: [for x in a {x}] -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 3 Allocs: 4 Retain: 0 Unifications: 7 Conjuncts: 8 Disjuncts: 7 -- out/eval -- Errors: a.1.b: conflicting values 3 and 2: ./in.cue:1:17 ./in.cue:1:21 Result: (_|_){ // [eval] a: (_|_){ // [eval] 0: (struct){ a: (int){ 1 } } 1: (_|_){ // [eval] b: (_|_){ // [eval] a.1.b: conflicting values 3 and 2: // ./in.cue:1:17 // ./in.cue:1:21 } } } b: (_|_){ // [eval] a.1.b: conflicting values 3 and 2: // ./in.cue:1:17 // ./in.cue:1:21 } } -- out/compile -- --- in.cue { a: [ { a: 1 }, { b: (2 & 3) }, ] b: [ for _, x in 〈1;a〉 { 〈1;x〉 }, ] } cue-lang-cue-db9cc73/cue/testdata/comprehensions/multi.txtar000066400000000000000000000031341474664451600243400ustar00rootroot00000000000000-- in.cue -- list: [2, 3] a: [ 3, for x in list {x}, for x in list {x}] b: [ 3, if true {3}, for x in list if x > 2 {x}] issue574: { greet: true bye: true message1: [ if greet {"hello"}, "how are you doing?", "bye", ] message2: [ if !greet {"hello"}, "how are you doing?", if bye { "bye" }, ] } -- out/eval/stats -- Leaks: 0 Freed: 24 Reused: 20 Allocs: 4 Retain: 0 Unifications: 24 Conjuncts: 37 Disjuncts: 24 -- out/eval -- (struct){ list: (#list){ 0: (int){ 2 } 1: (int){ 3 } } a: (#list){ 0: (int){ 3 } 1: (int){ 2 } 2: (int){ 3 } 3: (int){ 2 } 4: (int){ 3 } } b: (#list){ 0: (int){ 3 } 1: (int){ 3 } 2: (int){ 3 } } issue574: (struct){ greet: (bool){ true } bye: (bool){ true } message1: (#list){ 0: (string){ "hello" } 1: (string){ "how are you doing?" } 2: (string){ "bye" } } message2: (#list){ 0: (string){ "how are you doing?" } 1: (string){ "bye" } } } } -- out/compile -- --- in.cue { list: [ 2, 3, ] a: [ 3, for _, x in 〈1;list〉 { 〈1;x〉 }, for _, x in 〈1;list〉 { 〈1;x〉 }, ] b: [ 3, if true { 3 }, for _, x in 〈1;list〉 if (〈0;x〉 > 2) { 〈1;x〉 }, ] issue574: { greet: true bye: true message1: [ if 〈1;greet〉 { "hello" }, "how are you doing?", "bye", ] message2: [ if !〈1;greet〉 { "hello" }, "how are you doing?", if 〈1;bye〉 { "bye" }, ] } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/nested.txtar000066400000000000000000000107141474664451600244720ustar00rootroot00000000000000-- in.cue -- package kube service: "node-exporter": { spec: { ports: [{ name: "metrics" port: 9100 protocol: "TCP" }] } } deployment: "node-exporter": { spec: template: { spec: { containers: [{ ports: [{ containerPort: 9100 name: "scrape" }] }] } } } service: [ID=string]: { spec: { ports: [...{ port: int protocol: *"TCP" | "UDP" name: string | *"client" }] } } deployment: [ID=string]: {} deployment: [ID=_]: _spec & {} _spec: { _name: string spec: template: { spec: containers: [{name: _name}] } } _spec: spec: template: spec: containers: [...{ ports: [...{ _export: *true | false // include the port in the service }] }] for k, v in deployment { service: "\(k)": { spec: selector: v.spec.template.metadata.labels spec: ports: [ for c in v.spec.template.spec.containers for p in c.ports if p._export { let Port = p.containerPort // Port is an alias port: *Port | int targetPort: *Port | int }, ] } } -- out/eval/stats -- Leaks: 0 Freed: 45 Reused: 26 Allocs: 19 Retain: 33 Unifications: 35 Conjuncts: 95 Disjuncts: 75 -- out/eval -- (struct){ service: (struct){ "node-exporter": (struct){ spec: (struct){ ports: (#list){ 0: (struct){ name: (string){ "metrics" } port: (int){ 9100 } protocol: (string){ "TCP" } let Port#1 = (int){ 9100 } targetPort: (int){ |(*(int){ 9100 }, (int){ int }) } } } selector: (_|_){ // [incomplete] service."node-exporter".spec.selector: undefined field: metadata: // ./in.cue:48:35 } } } } deployment: (struct){ "node-exporter": (struct){ spec: (struct){ template: (struct){ spec: (struct){ containers: (#list){ 0: (struct){ ports: (#list){ 0: (struct){ containerPort: (int){ 9100 } name: (string){ "scrape" } _export(:kube): (bool){ |(*(bool){ true }, (bool){ false }) } } } name: (string){ string } } } } } } _name(:kube): (string){ string } } } _spec(:kube): (struct){ _name(:kube): (string){ string } spec: (struct){ template: (struct){ spec: (struct){ containers: (#list){ 0: (struct){ name: (string){ string } ports: (list){ } } } } } } } } -- out/compile -- --- in.cue { service: { "node-exporter": { spec: { ports: [ { name: "metrics" port: 9100 protocol: "TCP" }, ] } } } deployment: { "node-exporter": { spec: { template: { spec: { containers: [ { ports: [ { containerPort: 9100 name: "scrape" }, ] }, ] } } } } } service: { [string]: { spec: { ports: [ ...{ port: int protocol: (*"TCP"|"UDP") name: (string|*"client") }, ] } } } deployment: { [string]: {} } deployment: { [_]: (〈1;_spec〉 & {}) } _spec: { _name: string spec: { template: { spec: { containers: [ { name: 〈5;_name〉 }, ] } } } } _spec: { spec: { template: { spec: { containers: [ ...{ ports: [ ...{ _export: (*true|false) }, ] }, ] } } } } for k, v in 〈0;deployment〉 { service: { "\(〈2;k〉)": { spec: { selector: 〈4;v〉.spec.template.metadata.labels } spec: { ports: [ for _, c in 〈5;v〉.spec.template.spec.containers for _, p in 〈0;c〉.ports if 〈0;p〉._export { let Port#1 = 〈1;p〉.containerPort port: (*〈0;let Port#1〉|int) targetPort: (*〈0;let Port#1〉|int) }, ] } } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/nested2.txtar000066400000000000000000000104061474664451600245520ustar00rootroot00000000000000-- in.cue -- given: { INC: USD: 2.0 USD: GBP: 3.0 } hydrated: { for k, v in given { for k1, r in v { "\(k)": "\(k)": 1.0 "\(k1)": "\(k1)": 1.0 "\(k)": "\(k1)": r "\(k1)": "\(k)": number } } } foo: { a: 10 if a < 20 { if a < 50 { b: 20 } } } indirectlyNested: { a: true // must be declared outside of the nested comprehensions for test. if true { b: { if a { a } } } } directlyNestedEmpty: { a: true if true { if a { } } } directlyDoublyNestedEmpty: { a: true if true { if a { } } } indirectlyDoublyNestedEmpty: { a: true b: { if true { if a { if a { a } } if a { a } } } } indirectlyDoublyNested: { a: true if true { if a { if a { b: 1 } } if a { c: 1 } } } // This case used to trigger an over-aggressive deduplication. issue1974: { X: { foo: { bar: "" baz: "" } } out: { for k, v in X for vk, vv in v { "\(k)": "\(vk)": vv } } } -- pending.cue -- // Trigger notification while an arc is still pending. T: int for C in Y { let X = C.M T: X.V } Y: x: { M: V: 1 for _ in M { if true { M: {} } } } -- out/eval/stats -- Leaks: 2 Freed: 50 Reused: 45 Allocs: 7 Retain: 12 Unifications: 52 Conjuncts: 91 Disjuncts: 57 -- out/eval -- (struct){ given: (struct){ INC: (struct){ USD: (float){ 2.0 } } USD: (struct){ GBP: (float){ 3.0 } } } hydrated: (struct){ INC: (struct){ INC: (float){ 1.0 } USD: (float){ 2.0 } } USD: (struct){ USD: (float){ 1.0 } INC: (number){ number } GBP: (float){ 3.0 } } GBP: (struct){ GBP: (float){ 1.0 } USD: (number){ number } } } foo: (struct){ a: (int){ 10 } b: (int){ 20 } } indirectlyNested: (struct){ a: (bool){ true } b: (bool){ true } } directlyNestedEmpty: (struct){ a: (bool){ true } } directlyDoublyNestedEmpty: (struct){ a: (bool){ true } } indirectlyDoublyNestedEmpty: (struct){ a: (bool){ true } b: (bool){ true } } indirectlyDoublyNested: (struct){ a: (bool){ true } c: (int){ 1 } b: (int){ 1 } } issue1974: (struct){ X: (struct){ foo: (struct){ bar: (string){ "" } baz: (string){ "" } } } out: (struct){ foo: (struct){ bar: (string){ "" } baz: (string){ "" } } } } T: (int){ 1 } let X#1multi = 〈1;C〉.M Y: (struct){ x: (struct){ M: (struct){ V: (int){ 1 } } } } } -- out/compile -- --- in.cue { given: { INC: { USD: 2.0 } USD: { GBP: 3.0 } } hydrated: { for k, v in 〈1;given〉 { for k1, r in 〈1;v〉 { "\(〈3;k〉)": { "\(〈4;k〉)": 1.0 } "\(〈1;k1〉)": { "\(〈2;k1〉)": 1.0 } "\(〈3;k〉)": { "\(〈2;k1〉)": 〈2;r〉 } "\(〈1;k1〉)": { "\(〈4;k〉)": number } } } } foo: { a: 10 if (〈0;a〉 < 20) { if (〈1;a〉 < 50) { b: 20 } } } indirectlyNested: { a: true if true { b: { if 〈2;a〉 { 〈3;a〉 } } } } directlyNestedEmpty: { a: true if true { if 〈1;a〉 {} } } directlyDoublyNestedEmpty: { a: true if true { if 〈1;a〉 {} } } indirectlyDoublyNestedEmpty: { a: true b: { if true { if 〈2;a〉 { if 〈3;a〉 { 〈4;a〉 } } if 〈2;a〉 { 〈3;a〉 } } } } indirectlyDoublyNested: { a: true if true { if 〈1;a〉 { if 〈2;a〉 { b: 1 } } if 〈1;a〉 { c: 1 } } } issue1974: { X: { foo: { bar: "" baz: "" } } out: { for k, v in 〈1;X〉 for vk, vv in 〈0;v〉 { "\(〈2;k〉)": { "\(〈2;vk〉)": 〈2;vv〉 } } } } } --- pending.cue { T: int for _, C in 〈0;Y〉 { let X#1multi = 〈1;C〉.M T: 〈0;let X#1〉.V } Y: { x: { M: { V: 1 } for _, _ in 〈0;M〉 { if true { M: {} } } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/nestembed.txtar000066400000000000000000000037521474664451600251620ustar00rootroot00000000000000Issue #556 -- in.cue -- import "list" DeleteThis: ["this", "that"] useful_infra: { gcp: cluters: 10 aws: clusters: 20 this: clusters: 1 that: clusters: 2 } New_infra: { for k, v in useful_infra { if !list.Contains(DeleteThis, k) { "\(k)": v } } } -- out/eval/stats -- Leaks: 0 Freed: 18 Reused: 14 Allocs: 4 Retain: 0 Unifications: 18 Conjuncts: 26 Disjuncts: 18 -- out/evalalpha -- (struct){ DeleteThis: (#list){ 0: (string){ "this" } 1: (string){ "that" } } useful_infra: (struct){ gcp: (struct){ cluters: (int){ 10 } } aws: (struct){ clusters: (int){ 20 } } this: (struct){ clusters: (int){ 1 } } that: (struct){ clusters: (int){ 2 } } } New_infra: (struct){ gcp: ~(useful_infra.gcp) aws: ~(useful_infra.aws) } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -18,11 +18,7 @@ } } New_infra: (struct){ - gcp: (struct){ - cluters: (int){ 10 } - } - aws: (struct){ - clusters: (int){ 20 } - } + gcp: ~(useful_infra.gcp) + aws: ~(useful_infra.aws) } } -- out/eval -- (struct){ DeleteThis: (#list){ 0: (string){ "this" } 1: (string){ "that" } } useful_infra: (struct){ gcp: (struct){ cluters: (int){ 10 } } aws: (struct){ clusters: (int){ 20 } } this: (struct){ clusters: (int){ 1 } } that: (struct){ clusters: (int){ 2 } } } New_infra: (struct){ gcp: (struct){ cluters: (int){ 10 } } aws: (struct){ clusters: (int){ 20 } } } } -- out/compile -- --- in.cue { DeleteThis: [ "this", "that", ] useful_infra: { gcp: { cluters: 10 } aws: { clusters: 20 } this: { clusters: 1 } that: { clusters: 2 } } New_infra: { for k, v in 〈1;useful_infra〉 { if !〈import;list〉.Contains(〈3;DeleteThis〉, 〈1;k〉) { "\(〈2;k〉)": 〈2;v〉 } } } } cue-lang-cue-db9cc73/cue/testdata/comprehensions/pushdown.txtar000066400000000000000000002111261474664451600250570ustar00rootroot00000000000000# Working set of tests that unit test specifics of the aspect of the # comprehension algorithm that pushes down evaluation to the arcs. -- in.cue -- linkChildren: { w: 1 v: { x: 1 if true { y: 1 if true { z: 1 rw: w rx: x ry: y rz: z n1a: na: [w, x, y, z] n2a: n1a: na: [w, x, y, z] n2z: n1z: nz: z } } } } fail: { a: { // Condition of comprehensions must still hold after its evaluation. // // `b` is not defined, causing this if comprehension to evaluate to // true. However, after inserting the corresponding result in curly // braces, the condition would be true. This is not allowed. if a.b == _|_ { b: 1 } } } embed: { fail1: #C1 #C1: { // TODO(errors): don't include all positions of p in the normal list of // positions, or rather categorize the positions to show: // 1) position of denied fields // 2) position of structs that deny them // 3) points at which those structs where mixed in (perhaps as tree) // 4) conditionals that could enable allowing a field. if false { p: _ } } fail1: p: "foo" // this should fail, as p is not present. success2: #C2 #C2: { if true { p: _ } } success2: p: "foo" // this succeeds as p is present. success3: #C3 #C3: {} success3: { if false { // p does not exist in success3, but it is okay, as it is not added. p: q: 1 } } success4: { #X: y: string x: y: string x: { for _ in ["iter-once"] { #X if false { y: "foo" } } } } fail4: #C4 #C4: {} fail4: { if true { // error as p is not allowed in fail4 p: q: 1 } } incomplete5: { a: bool if a { p: q: 1 } } incomplete6: { if false { p: 1 } p: q + 1 q: int } incomplete7: { p: q + 1 q: int if false { q: 1 // do not inadvertently pick up a void arc. } } } // Mix of both dynamic and static fields. mixedFieldsSuccess: { a: { for _, s in ["foo"] { "\(s)": 1 X: 1 } } b: #Def: { for _, s in ["foo"] { "\(s)": 1 X: 1 } } b: x: b.#Def b: x: X: _ b: x: foo: _ c: #Def: { X: int foo: int } c: x: c.#Def c: x: { for _, s in ["foo"] { "\(s)": 1 X: 1 } } } // fieldMismatch tests that an embedded scalar cannot be mixed with regular // fields, even if they are added by a comprehension. fieldMismatch: { a: { 2 if true { x: 3 } } } // b12aStructCycle presents a case that can easily lead to stack overflow in // a naive implementation. It corresponds to test b12a in structural.txtar. noStackOverflowStructCycle: { #list: { tail: #list if tail != null { sum: tail.sum } } list: { tail: list if tail != null { sum: tail.sum } } } // #a is incomplete, but the missing values are provided by x. provideIncompleteSuccess: { t1: { #a: { if b { c: 4 } b: bool } x: (#a & {b: true}) & {c: 4} y: x } t2: { // c should be allowed #a: { if b { c: 4 } b: true } #c: {} a: { if b { c: d: 4 } b: true // d is disallowed, even though it is added by embedding. // TODO: this seems right, but it may be good to clarify why. c: #c } } } // voidArcs tests that fields are dropped and reference up counts are adjusted // appropriately under various rewrite scenario. voidArcs: { scopes: { x: 1 a: { y: 2 if true { b: x c: d: x e: y f: g: y } } } drop: { x: 1 a: { y: 2 if false { b: x c: d: x e: y f: g: y } } } } cyclicError: { a: { x: bool y: bool if a.x { y: true } if a.y { x: true } b: {} } // The evaluation of `b` in `a` triggers a to be fully evaluated, which // is not possible because the evaluation of `a` depends on incomplete // values. c: a.b } midwayReferences: { a: { for i, j in {a: 1, b: 2} { x: y: z: (i): j } x: y: {} } b: a.x c: a.x.y d: a.x.y.z } // Ensure first closedness check is done after evaluation of // comprehensions. closedCheck: success1: { a: b: [string]: #D #D: { d: string if d != "c" { e: string } } a: b: c: { d: "d" e: "ok" } } closedCheck: success2: { a: b: [string]: #D #D: { d: string if d != "c" { ("foo"+"bar"): string } } a: b: c: { d: "d" foobar: "ok" } } closedCheck: success3: { a: b: [string]: #D #D: { d: string e: { if d != "c" { string } } } a: b: c: { d: "d" e: "ok" } } emptyComprehensionIncomplete: { a: {} b: { // b should be an incomplete error if a.b { } } } // voidEliminationSuccess tests that "conditional" or "void" arcs are eliminated // if their expression does not yield any result. voidEliminationSuccess: t1: { [string]: { b: bool if !b {} } if false { a: b: true } } voidEliminationSuccess: t2: { components: { sinks: [string]: #C & { kind: string configuration: { if kind != "source" { inputs: { required: true } } } } #C: { kind: string configuration: [string]: { required: bool if !required { common: bool } } } } components: sinks: blah: { kind: "source" } } voidEliminationSuccess: derefRef1: { a: [string]: c: [string]: E a: b: c: { if false { d: e: true // resolves } } E: { e: bool f: !e // remains incomplete } } voidEliminationSuccess: derefRef2: { a: [string]: c: [string]: E a: b: c: { if false { d: e: true // resolves } } E: #F #F: { e: bool f: !e // remains incomplete } } voidEliminationSuccess: derefDisj1: { a: [string]: c: [string]: E a: b: c: { if false { d: e: true } } E: { e: bool f: !e } | { g: bool h: !g } } voidEliminationSuccess: derefDisj2: { a: [string]: c: [string]: E & E a: b: c: { if false { d: e: true } } E: { e: bool f: !e } | { g: bool h: !g } } voidEliminationSuccess: bulk1: { a: b: {} a: [string]: { c: { e: string if false { e: "" } } d: c.e } } voidEliminationSuccess: opt1: { a: b: {} a: b?: { c: { e: string if false { e: "" } } d: c.e } } voidEliminationSuccess: noCycle1: { _x: a.b a: { c: h: "stream" b: { if c.g != _|_ {} } c: { if false {g: _} } } } voidEliminationSuccess: noCycle2: { a: { c: h: "stream" b: { if c.g != _|_ {} } c: { if false {g: _} } } _x: a.b } voidLookup: { a: x: z: a.y.z.void a: y: { c: _ z: {} } a: [string]: { c: { for k, v in z { (k): null // don't add this arc anywhere } } z: { if false { err: {} } } } } // Eliminate the top value even if there is an error (especially incomplete // errors). topElimination: { a: int _ if true { x: a+1 } } voidEliminationSuccess: drop1: { // Do not include x in s. t: { #ok: *true | bool if #ok { x: int } } s: t & { #ok: false } } // should be error // issue #465 explicitDefaultError: { a: string | *_|_ if a != "" { } } // Remove arcs for with no for comprehension results. allArcsSuccess: p1: { x: { for k, _ in y { (k): null } } y: { if false { x: {} } } } allArcsSuccess: p2: { y: { if false { x: {} } } x: { for k, _ in y { (k): null } } } structShare: ok1: { a: [string]: E E: {} a: { if true { d: e: true // resolves } } } structShare: err1: { x: [string]: x.#E x: #E: {} if true { x: d: e: true } } -- issue2208.cue -- voidErrorIncomplete: { #Schema: [string]: { required: bool if !required { } } root: #Schema root: { if false { child: required: false } } } // TODO: should these always be errors, or only for cue vet? // voidErrorFatal: pattern: { // #Schema: [string]: { // if "str" + 3 { // } // } // // root: #Schema // root: { // if false { // child: required: false // } // } // } // // voidErrorFatal: field: { // root: { // if false { // child: 2 + "str" // } // } // } -- issue1759.cue -- // Tests derived from Unity. unity: success1: { #Config: { name: string type: string } #AnyConfig: { #Config ... } #Env: { name: string configurations: [string]: #AnyConfig } envs: "e1": #Env & { configurations: c1: #Config } envs: [string]: configurations: [string]: { type: "foo" if type == "terraform" { backend: { type: "s3" } } } } issue1759: { _ports_map: {} if len(_ports_map) > 0 { port: _ports_map.a.port } if true { _ports_map: a: {port: "80"} } } arcAlignment: t1: { [string]: { if true { } } if false { c: _ } } -- issue2111.cue -- // All arc types, not just regular fields, should be pushed down. letPushdown: { _c: y: 1 a: { for k, v in _c { let x = v if x != _|_ { } } } } -- issue2113.cue -- // Ensure that an enclosing Value clause of a nested comprehension is evaluated // before the nested comprehension itself is evaluated. nestedWithEmbeddingOK: { c: [1] a: { for k, v in c { {x: 1} if a.x != _|_ { } } } } nestedWithDynamicFieldOK: { _c: y: 1 a: { for k, v in _c { if x != _|_ { } x="\(k)": 1 } } } // Errors in nested comprehensions should also be reported. errorPropagation: { deployment: _ for k, v in deployment { for k1, v2 in v.env2 { // Report this error. deployment: (k): x1: 1 } } for id in ["elem"] { deployment: (id): x2: 2 } } -- issue2131.cue -- import "path" issue2131: tests: { windows: { eg1: in: #"c:\d"# eg2: in: #"c:\test"# eg3: in: #"c:\test\d"# } for os, examples in tests for k, v in examples { (os): (k): out: "test" } } -- issue3533.cue -- issue3533: { #ObjectMeta: namespace?: string out: { for i, _ in ["iter-once"] { metadata: #ObjectMeta if false { metadata: namespace: "foo" } } } out: metadata: namespace: *"default" | string } -- issue3535.cue -- issue3535: hidden: { #X: { kind: string output: {} } foo: #X & { kind: string if kind == "foo" { _hidden: {} } } foo: kind: "foo" } issue3535: regular: { #X: { kind: string output: {} } foo: #X & { kind: string if kind == "foo" { regular: {} } } foo: kind: "foo" } issue3535: def: { #X: { kind: string output: {} } foo: #X & { kind: string if kind == "foo" { #def: {} } } foo: kind: "foo" } -- reflect.cue -- import "encoding/json" unifyDynamicReflectSuccess: { for _, s in ["foo"] { X: {...} "\(s)": { X: {...} // cannot be _ Y: json.Marshal(X) // cannot be yaml, X cannot be literal } } [string]: X: { if true {// must be there x: y: {} // at least 2 nestings needed to expose problem } } } -- issue3621.cue -- issue3621: reduced: t1: { // This test ensures that when a reference is made within a comprehension, // with vertices marked as "pending", that these are not completed the // respective pushed-down comprehension is evaluated as well. if true { a: b1.b2.b3 b1: b2: b3: "Foo" } } issue3621: reduced: t2: { outer: {} if true { inner: inner2: name: "Foo" outer: b: inner.inner2.name } } issue3621: full: { hello: "world" outer: [Name=string]: name: Name if true { inner: inner2: { name: "Employees" description: "All employees" privacy: "secret" create_default: false } outer: outer2: { bar: (inner.inner2.name) } } } -- out/evalalpha/stats -- Leaks: 513 Freed: 2 Reused: 2 Allocs: 513 Retain: 0 Unifications: 489 Conjuncts: 2982 Disjuncts: 22 -- out/evalalpha -- Errors: noStackOverflowStructCycle.#list.tail: structural cycle noStackOverflowStructCycle.list.tail: structural cycle embed.fail1.p: field not allowed: ./in.cue:46:7 ./in.cue:46:4 ./in.cue:49:9 embed.fail4.p: field not allowed: ./in.cue:87:10 ./in.cue:87:4 fieldMismatch.a: cannot combine regular field "x" with 2: ./in.cue:152:7 ./in.cue:150:3 structShare.err1.x.d.e: field not allowed: ./in.cue:591:12 ./in.cue:591:9 issue3535.regular.foo.regular: field not allowed: ./issue3535.cue:22:13 ./issue3535.cue:22:4 Result: (_|_){ // [eval] linkChildren: (struct){ w: (int){ 1 } v: (struct){ x: (int){ 1 } y: (int){ 1 } z: (int){ 1 } rw: (int){ 1 } rx: (int){ 1 } ry: (int){ 1 } rz: (int){ 1 } n1a: (struct){ na: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } } } n2a: (struct){ n1a: (struct){ na: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } } } } n2z: (struct){ n1z: (struct){ nz: (int){ 1 } } } } } fail: (struct){ a: (_|_){ // [incomplete] fail.a.b: cyclic reference to field b: // ./in.cue:30:3 } } embed: (_|_){ // [eval] fail1: (_|_){ // [eval] p: (_|_){ // [eval] embed.fail1.p: field not allowed: // ./in.cue:46:7 // ./in.cue:46:4 // ./in.cue:49:9 } } #C1: (#struct){ } success2: (#struct){ p: (string){ "foo" } } #C2: (#struct){ p: (_){ _ } } success3: (#struct){ } #C3: (#struct){ } success4: (struct){ #X: (#struct){ y: (string){ string } } x: (#struct){ y: (string){ string } } } fail4: (_|_){ // [eval] p: (_|_){ // [eval] embed.fail4.p: field not allowed: // ./in.cue:87:10 // ./in.cue:87:4 q: (int){ 1 } } } #C4: (#struct){ } incomplete5: (_|_){ // [incomplete] embed.incomplete5: incomplete bool: bool: // ./in.cue:92:6 a: (bool){ bool } } incomplete6: (struct){ p: (_|_){ // [incomplete] embed.incomplete6.p: non-concrete value int in operand to +: // ./in.cue:102:6 // ./in.cue:103:6 } q: (int){ int } } incomplete7: (struct){ p: (_|_){ // [incomplete] embed.incomplete7.p: non-concrete value int in operand to +: // ./in.cue:106:6 // ./in.cue:107:6 // ./in.cue:108:3 } q: (int){ int } } } mixedFieldsSuccess: (struct){ a: (struct){ X: (int){ 1 } foo: (int){ 1 } } b: (struct){ #Def: (#struct){ X: (int){ 1 } foo: (int){ 1 } } x: (#struct){ X: (int){ 1 } foo: (int){ 1 } } } c: (struct){ #Def: (#struct){ X: (int){ int } foo: (int){ int } } x: (#struct){ X: (int){ 1 } foo: (int){ 1 } } } } fieldMismatch: (_|_){ // [eval] a: (_|_){ // [eval] fieldMismatch.a: cannot combine regular field "x" with 2: // ./in.cue:152:7 // ./in.cue:150:3 x: (int){ 3 } } } noStackOverflowStructCycle: (_|_){ // [structural cycle] #list: (_|_){ // [structural cycle] noStackOverflowStructCycle.#list.tail: structural cycle } list: (_|_){ // [structural cycle] noStackOverflowStructCycle.list.tail: structural cycle } } provideIncompleteSuccess: (struct){ t1: (struct){ #a: (_|_){ // [incomplete] provideIncompleteSuccess.t1.#a: incomplete bool: bool: // ./in.cue:185:7 b: (bool){ bool } } x: (#struct){ b: (bool){ true } c: (int){ 4 } } y: ~(provideIncompleteSuccess.t1.x) } t2: (struct){ #a: (#struct){ c: (int){ 4 } b: (bool){ true } } #c: (#struct){ } a: (struct){ c: (#struct){ } b: (bool){ true } } } } voidArcs: (struct){ scopes: (struct){ x: (int){ 1 } a: (struct){ y: (int){ 2 } b: (int){ 1 } c: (struct){ d: (int){ 1 } } e: (int){ 2 } f: (struct){ g: (int){ 2 } } } } drop: (struct){ x: (int){ 1 } a: (struct){ y: (int){ 2 } } } } cyclicError: (struct){ a: (_|_){ // [incomplete] cyclicError.a: incomplete bool: bool: // ./in.cue:246:6 x: (_|_){ // [incomplete] cyclicError.a: incomplete bool: bool: // ./in.cue:246:6 } y: (bool){ bool } b: (struct){ } } c: (_|_){ // [incomplete] cyclicError.a: incomplete bool: bool: // ./in.cue:246:6 } } midwayReferences: (struct){ a: (struct){ x: (struct){ y: (struct){ z: (struct){ a: (int){ 1 } b: (int){ 2 } } } } } b: ~(midwayReferences.a.x) c: ~(midwayReferences.a.x.y) d: ~(midwayReferences.a.x.y.z) } closedCheck: (struct){ success1: (struct){ a: (struct){ b: (struct){ c: (#struct){ d: (string){ "d" } e: (string){ "ok" } } } } #D: (_|_){ // [incomplete] closedCheck.success1.#D: non-concrete value string in operand to !=: // ./in.cue:280:6 // ./in.cue:279:6 d: (string){ string } } } success2: (struct){ a: (struct){ b: (struct){ c: (#struct){ d: (string){ "d" } foobar: (string){ "ok" } } } } #D: (_|_){ // [incomplete] closedCheck.success2.#D: non-concrete value string in operand to !=: // ./in.cue:296:6 // ./in.cue:295:6 d: (string){ string } } } success3: (struct){ a: (struct){ b: (struct){ c: (#struct){ d: (string){ "d" } e: (string){ "ok" } } } } #D: (#struct){ d: (string){ string } e: (_|_){ // [incomplete] closedCheck.success3.#D.e: non-concrete value string in operand to !=: // ./in.cue:313:7 // ./in.cue:311:6 } } } } emptyComprehensionIncomplete: (struct){ a: (struct){ } b: (_|_){ // [incomplete] emptyComprehensionIncomplete.b: undefined field: b: // ./in.cue:329:8 } } voidEliminationSuccess: (struct){ t1: (struct){ } t2: (struct){ components: (struct){ sinks: (struct){ blah: (#struct){ kind: (string){ "source" } configuration: (#struct){ } } } #C: (#struct){ kind: (string){ string } configuration: (#struct){ } } } } derefRef1: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (struct){ e: (bool){ bool } f: (_|_){ // [incomplete] voidEliminationSuccess.derefRef1.E.f: operand e of '!' not concrete (was bool): // ./in.cue:386:7 } } } derefRef2: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: ~(voidEliminationSuccess.derefRef2.#F) #F: (#struct){ e: (bool){ bool } f: (_|_){ // [incomplete] voidEliminationSuccess.derefRef2.#F.f: operand e of '!' not concrete (was bool): // ./in.cue:402:7 } } } derefDisj1: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (_|_){ // [incomplete] voidEliminationSuccess.derefDisj1.E: 2 errors in empty disjunction: // voidEliminationSuccess.derefDisj1.E.f: operand e of '!' not concrete (was bool): // ./in.cue:417:7 // voidEliminationSuccess.derefDisj1.E.h: operand g of '!' not concrete (was bool): // ./in.cue:420:7 } } derefDisj2: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (_|_){ // [incomplete] voidEliminationSuccess.derefDisj2.E: 2 errors in empty disjunction: // voidEliminationSuccess.derefDisj2.E.f: operand e of '!' not concrete (was bool): // ./in.cue:435:7 // voidEliminationSuccess.derefDisj2.E.h: operand g of '!' not concrete (was bool): // ./in.cue:438:7 } } bulk1: (struct){ a: (struct){ b: (struct){ c: (struct){ e: (string){ string } } d: (string){ string } } } } opt1: (struct){ a: (struct){ b: (struct){ c: (struct){ e: (string){ string } } d: (string){ string } } } } noCycle1: (struct){ _x: (struct){ } a: (struct){ c: (struct){ h: (string){ "stream" } } b: (struct){ } } } noCycle2: (struct){ a: (struct){ c: (struct){ h: (string){ "stream" } } b: (struct){ } } _x: (struct){ } } drop1: (struct){ t: (struct){ #ok: (bool){ |(*(bool){ true }, (bool){ bool }) } x: (int){ int } } s: (struct){ #ok: (bool){ false } } } } voidLookup: (struct){ a: (struct){ x: (struct){ z: (_|_){ // [incomplete] voidLookup.a.x.z: undefined field: void: // ./in.cue:495:17 } c: (_|_){ // [incomplete] voidLookup.a.x.z: undefined field: void: // ./in.cue:495:17 } } y: (struct){ c: (_){ _ } z: (struct){ } } } } topElimination: (struct){ a: (int){ int } x: (_|_){ // [incomplete] topElimination.x: non-concrete value int in operand to +: // ./in.cue:523:6 // ./in.cue:520:5 } } explicitDefaultError: (_|_){ // [incomplete] explicitDefaultError: non-concrete value string in operand to !=: // ./in.cue:545:5 // ./in.cue:543:5 a: (string){ string } } allArcsSuccess: (struct){ p1: (struct){ x: (struct){ } y: (struct){ } } p2: (struct){ y: (struct){ } x: (struct){ } } } structShare: (_|_){ // [eval] ok1: (struct){ a: (struct){ d: (struct){ e: (bool){ true } } } E: (struct){ } } err1: (_|_){ // [eval] x: (_|_){ // [eval] #E: (#struct){ } d: (_|_){ // [eval] e: (_|_){ // [eval] structShare.err1.x.d.e: field not allowed: // ./in.cue:591:12 // ./in.cue:591:9 } } } } } unity: (struct){ success1: (struct){ #Config: (#struct){ name: (string){ string } type: (string){ string } } #AnyConfig: (#struct){ name: (string){ string } type: (string){ string } } #Env: (#struct){ name: (string){ string } configurations: (#struct){ } } envs: (struct){ e1: (#struct){ configurations: (#struct){ c1: (#struct){ type: (string){ "foo" } name: (string){ string } } } name: (string){ string } } } } } issue1759: (struct){ _ports_map: (struct){ a: (struct){ port: (string){ "80" } } } port: (string){ "80" } } arcAlignment: (struct){ t1: (struct){ } } letPushdown: (struct){ _c: (struct){ y: (int){ 1 } } a: (struct){ let x#1multi = 〈1;v〉 } } nestedWithEmbeddingOK: (struct){ c: (#list){ 0: (int){ 1 } } a: (struct){ x: (int){ 1 } } } nestedWithDynamicFieldOK: (struct){ _c: (struct){ y: (int){ 1 } } a: (struct){ y: (int){ 1 } } } errorPropagation: (_|_){ // [incomplete] errorPropagation: undefined field: env2: // ./issue2113.cue:30:19 deployment: (_|_){ // [incomplete] errorPropagation: undefined field: env2: // ./issue2113.cue:30:19 elem: (struct){ x2: (int){ 2 } } } } issue2131: (struct){ tests: (struct){ windows: (struct){ eg1: (struct){ in: (string){ "c:\\d" } out: (string){ "test" } } eg2: (struct){ in: (string){ "c:\\test" } out: (string){ "test" } } eg3: (struct){ in: (string){ "c:\\test\\d" } out: (string){ "test" } } } } } voidErrorIncomplete: (struct){ #Schema: (#struct){ } root: (#struct){ } } issue3533: (struct){ #ObjectMeta: (#struct){ namespace?: (string){ string } } out: (struct){ metadata: (#struct){ namespace: (string){ |(*(string){ "default" }, (string){ string }) } } } } issue3535: (_|_){ // [eval] hidden: (struct){ #X: (#struct){ kind: (string){ string } output: (#struct){ } } foo: (#struct){ kind: (string){ "foo" } _hidden: (struct){ } output: (#struct){ } } } regular: (_|_){ // [eval] #X: (#struct){ kind: (string){ string } output: (#struct){ } } foo: (_|_){ // [eval] kind: (string){ "foo" } regular: (_|_){ // [eval] issue3535.regular.foo.regular: field not allowed: // ./issue3535.cue:22:13 // ./issue3535.cue:22:4 } output: (#struct){ } } } def: (struct){ #X: (#struct){ kind: (string){ string } output: (#struct){ } } foo: (#struct){ kind: (string){ "foo" } #def: (#struct){ } output: (#struct){ } } } } issue3621: (struct){ reduced: (struct){ t1: (struct){ a: (string){ "Foo" } b1: (struct){ b2: (struct){ b3: (string){ "Foo" } } } } t2: (struct){ outer: (struct){ b: (string){ "Foo" } } inner: (struct){ inner2: (struct){ name: (string){ "Foo" } } } } } full: (struct){ hello: (string){ "world" } outer: (struct){ outer2: (struct){ bar: (string){ "Employees" } name: (string){ "outer2" } } } inner: (struct){ inner2: (struct){ name: (string){ "Employees" } description: (string){ "All employees" } privacy: (string){ "secret" } create_default: (bool){ false } } } } } unifyDynamicReflectSuccess: (struct){ X: (struct){ X: (struct){ x: (struct){ y: (struct){ } } } } foo: (struct){ X: (struct){ x: (struct){ y: (struct){ } } } Y: (string){ "{\"x\":{\"y\":{}}}" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,39 +1,22 @@ Errors: +noStackOverflowStructCycle.#list.tail: structural cycle +noStackOverflowStructCycle.list.tail: structural cycle embed.fail1.p: field not allowed: - ./in.cue:37:9 - ./in.cue:38:7 - ./in.cue:45:3 - ./in.cue:45:12 + ./in.cue:46:7 ./in.cue:46:4 ./in.cue:49:9 embed.fail4.p: field not allowed: - ./in.cue:82:9 - ./in.cue:83:7 - ./in.cue:84:9 - ./in.cue:85:3 + ./in.cue:87:10 ./in.cue:87:4 -issue3535.regular.foo.regular: field not allowed: - ./issue3535.cue:15:6 - ./issue3535.cue:19:7 - ./issue3535.cue:19:12 - ./issue3535.cue:21:3 - ./issue3535.cue:22:4 - ./issue3535.cue:25:7 -noStackOverflowStructCycle.#list.tail: structural cycle -noStackOverflowStructCycle.list.tail: structural cycle -provideIncompleteSuccess.t2.a.c.d: field not allowed: - ./in.cue:200:7 - ./in.cue:202:4 - ./in.cue:203:8 - ./in.cue:208:7 -structShare.err1.x.d.e: field not allowed: - ./in.cue:588:15 - ./in.cue:589:9 - ./in.cue:590:2 - ./in.cue:591:9 fieldMismatch.a: cannot combine regular field "x" with 2: ./in.cue:152:7 ./in.cue:150:3 +structShare.err1.x.d.e: field not allowed: + ./in.cue:591:12 + ./in.cue:591:9 +issue3535.regular.foo.regular: field not allowed: + ./issue3535.cue:22:13 + ./issue3535.cue:22:4 Result: (_|_){ @@ -75,8 +58,8 @@ } fail: (struct){ a: (_|_){ - // [cycle] fail.a: cycle with field a.b: - // ./in.cue:30:6 + // [incomplete] fail.a.b: cyclic reference to field b: + // ./in.cue:30:3 } } embed: (_|_){ @@ -85,10 +68,7 @@ // [eval] p: (_|_){ // [eval] embed.fail1.p: field not allowed: - // ./in.cue:37:9 - // ./in.cue:38:7 - // ./in.cue:45:3 - // ./in.cue:45:12 + // ./in.cue:46:7 // ./in.cue:46:4 // ./in.cue:49:9 } @@ -117,10 +97,7 @@ // [eval] p: (_|_){ // [eval] embed.fail4.p: field not allowed: - // ./in.cue:82:9 - // ./in.cue:83:7 - // ./in.cue:84:9 - // ./in.cue:85:3 + // ./in.cue:87:10 // ./in.cue:87:4 q: (int){ 1 } } @@ -194,8 +171,7 @@ // [structural cycle] noStackOverflowStructCycle.list.tail: structural cycle } } - provideIncompleteSuccess: (_|_){ - // [eval] + provideIncompleteSuccess: (struct){ t1: (struct){ #a: (_|_){ // [incomplete] provideIncompleteSuccess.t1.#a: incomplete bool: bool: @@ -203,16 +179,12 @@ b: (bool){ bool } } x: (#struct){ - c: (int){ 4 } - b: (bool){ true } - } - y: (#struct){ - c: (int){ 4 } - b: (bool){ true } - } - } - t2: (_|_){ - // [eval] + b: (bool){ true } + c: (int){ 4 } + } + y: ~(provideIncompleteSuccess.t1.x) + } + t2: (struct){ #a: (#struct){ c: (int){ 4 } b: (bool){ true } @@ -219,17 +191,8 @@ } #c: (#struct){ } - a: (_|_){ - // [eval] - c: (_|_){ - // [eval] - d: (_|_){ - // [eval] provideIncompleteSuccess.t2.a.c.d: field not allowed: - // ./in.cue:200:7 - // ./in.cue:202:4 - // ./in.cue:203:8 - // ./in.cue:208:7 - } + a: (struct){ + c: (#struct){ } b: (bool){ true } } @@ -259,9 +222,19 @@ } cyclicError: (struct){ a: (_|_){ - // [cycle] cycle error - } - c: (struct){ + // [incomplete] cyclicError.a: incomplete bool: bool: + // ./in.cue:246:6 + x: (_|_){ + // [incomplete] cyclicError.a: incomplete bool: bool: + // ./in.cue:246:6 + } + y: (bool){ bool } + b: (struct){ + } + } + c: (_|_){ + // [incomplete] cyclicError.a: incomplete bool: bool: + // ./in.cue:246:6 } } midwayReferences: (struct){ @@ -275,24 +248,9 @@ } } } - b: (struct){ - y: (struct){ - z: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - } - } - c: (struct){ - z: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - } - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } + b: ~(midwayReferences.a.x) + c: ~(midwayReferences.a.x.y) + d: ~(midwayReferences.a.x.y.z) } closedCheck: (struct){ success1: (struct){ @@ -395,13 +353,7 @@ } } } - E: (#struct){ - e: (bool){ bool } - f: (_|_){ - // [incomplete] voidEliminationSuccess.derefRef2.E.f: operand e of '!' not concrete (was bool): - // ./in.cue:402:7 - } - } + E: ~(voidEliminationSuccess.derefRef2.#F) #F: (#struct){ e: (bool){ bool } f: (_|_){ @@ -418,17 +370,11 @@ } } E: (_|_){ - // [incomplete] voidEliminationSuccess.derefDisj1.E: 2 errors in empty disjunction:: - // ./in.cue:407:28 + // [incomplete] voidEliminationSuccess.derefDisj1.E: 2 errors in empty disjunction: // voidEliminationSuccess.derefDisj1.E.f: operand e of '!' not concrete (was bool): // ./in.cue:417:7 // voidEliminationSuccess.derefDisj1.E.h: operand g of '!' not concrete (was bool): // ./in.cue:420:7 - g: (bool){ bool } - h: (_|_){ - // [incomplete] voidEliminationSuccess.derefDisj1.E.h: operand g of '!' not concrete (was bool): - // ./in.cue:420:7 - } } } derefDisj2: (struct){ @@ -439,17 +385,11 @@ } } E: (_|_){ - // [incomplete] voidEliminationSuccess.derefDisj2.E: 2 errors in empty disjunction:: - // ./in.cue:425:28 + // [incomplete] voidEliminationSuccess.derefDisj2.E: 2 errors in empty disjunction: // voidEliminationSuccess.derefDisj2.E.f: operand e of '!' not concrete (was bool): // ./in.cue:435:7 // voidEliminationSuccess.derefDisj2.E.h: operand g of '!' not concrete (was bool): // ./in.cue:438:7 - g: (bool){ bool } - h: (_|_){ - // [incomplete] voidEliminationSuccess.derefDisj2.E.h: operand g of '!' not concrete (was bool): - // ./in.cue:438:7 - } } } bulk1: (struct){ @@ -572,9 +512,7 @@ // [eval] e: (_|_){ // [eval] structShare.err1.x.d.e: field not allowed: - // ./in.cue:588:15 - // ./in.cue:589:9 - // ./in.cue:590:2 + // ./in.cue:591:12 // ./in.cue:591:9 } } @@ -598,13 +536,13 @@ } envs: (struct){ e1: (#struct){ - name: (string){ string } configurations: (#struct){ c1: (#struct){ - name: (string){ string } type: (string){ "foo" } - } - } + name: (string){ string } + } + } + name: (string){ string } } } } @@ -641,9 +579,8 @@ _c: (struct){ y: (int){ 1 } } - a: (_|_){ - // [cycle] nestedWithDynamicFieldOK.a: circular dependency in evaluation of conditionals: "\(〈1;k〉)" changed after evaluation: - // ./issue2113.cue:19:7 + a: (struct){ + y: (int){ 1 } } } errorPropagation: (_|_){ @@ -701,10 +638,10 @@ } foo: (#struct){ kind: (string){ "foo" } - output: (#struct){ - } _hidden: (struct){ } + output: (#struct){ + } } } regular: (_|_){ @@ -717,16 +654,12 @@ foo: (_|_){ // [eval] kind: (string){ "foo" } - output: (#struct){ - } regular: (_|_){ // [eval] issue3535.regular.foo.regular: field not allowed: - // ./issue3535.cue:15:6 - // ./issue3535.cue:19:7 - // ./issue3535.cue:19:12 - // ./issue3535.cue:21:3 + // ./issue3535.cue:22:13 // ./issue3535.cue:22:4 - // ./issue3535.cue:25:7 + } + output: (#struct){ } } } @@ -738,10 +671,10 @@ } foo: (#struct){ kind: (string){ "foo" } - output: (#struct){ - } #def: (#struct){ } + output: (#struct){ + } } } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 15 -Freed: 394 -Reused: 388 -Allocs: 21 -Retain: 100 +Leaks: 513 +Freed: 2 +Reused: 2 +Allocs: 513 +Retain: 0 -Unifications: 395 -Conjuncts: 636 -Disjuncts: 464 +Unifications: 489 +Conjuncts: 2982 +Disjuncts: 22 -- out/eval/stats -- Leaks: 17 Freed: 468 Reused: 461 Allocs: 24 Retain: 103 Unifications: 469 Conjuncts: 747 Disjuncts: 541 -- diff/todo/p2 -- provideIncompleteSuccess.t2.a.c.d: missing error: probably correct. A bit esoteric, but should probably work. -- diff/explanation -- cyclicError: improved error message. nestedWithDynamicFieldOK: fixed bug. -- out/eval -- Errors: embed.fail1.p: field not allowed: ./in.cue:37:9 ./in.cue:38:7 ./in.cue:45:3 ./in.cue:45:12 ./in.cue:46:4 ./in.cue:49:9 embed.fail4.p: field not allowed: ./in.cue:82:9 ./in.cue:83:7 ./in.cue:84:9 ./in.cue:85:3 ./in.cue:87:4 issue3535.regular.foo.regular: field not allowed: ./issue3535.cue:15:6 ./issue3535.cue:19:7 ./issue3535.cue:19:12 ./issue3535.cue:21:3 ./issue3535.cue:22:4 ./issue3535.cue:25:7 noStackOverflowStructCycle.#list.tail: structural cycle noStackOverflowStructCycle.list.tail: structural cycle provideIncompleteSuccess.t2.a.c.d: field not allowed: ./in.cue:200:7 ./in.cue:202:4 ./in.cue:203:8 ./in.cue:208:7 structShare.err1.x.d.e: field not allowed: ./in.cue:588:15 ./in.cue:589:9 ./in.cue:590:2 ./in.cue:591:9 fieldMismatch.a: cannot combine regular field "x" with 2: ./in.cue:152:7 ./in.cue:150:3 Result: (_|_){ // [eval] linkChildren: (struct){ w: (int){ 1 } v: (struct){ x: (int){ 1 } y: (int){ 1 } z: (int){ 1 } rw: (int){ 1 } rx: (int){ 1 } ry: (int){ 1 } rz: (int){ 1 } n1a: (struct){ na: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } } } n2a: (struct){ n1a: (struct){ na: (#list){ 0: (int){ 1 } 1: (int){ 1 } 2: (int){ 1 } 3: (int){ 1 } } } } n2z: (struct){ n1z: (struct){ nz: (int){ 1 } } } } } fail: (struct){ a: (_|_){ // [cycle] fail.a: cycle with field a.b: // ./in.cue:30:6 } } embed: (_|_){ // [eval] fail1: (_|_){ // [eval] p: (_|_){ // [eval] embed.fail1.p: field not allowed: // ./in.cue:37:9 // ./in.cue:38:7 // ./in.cue:45:3 // ./in.cue:45:12 // ./in.cue:46:4 // ./in.cue:49:9 } } #C1: (#struct){ } success2: (#struct){ p: (string){ "foo" } } #C2: (#struct){ p: (_){ _ } } success3: (#struct){ } #C3: (#struct){ } success4: (struct){ #X: (#struct){ y: (string){ string } } x: (#struct){ y: (string){ string } } } fail4: (_|_){ // [eval] p: (_|_){ // [eval] embed.fail4.p: field not allowed: // ./in.cue:82:9 // ./in.cue:83:7 // ./in.cue:84:9 // ./in.cue:85:3 // ./in.cue:87:4 q: (int){ 1 } } } #C4: (#struct){ } incomplete5: (_|_){ // [incomplete] embed.incomplete5: incomplete bool: bool: // ./in.cue:92:6 a: (bool){ bool } } incomplete6: (struct){ p: (_|_){ // [incomplete] embed.incomplete6.p: non-concrete value int in operand to +: // ./in.cue:102:6 // ./in.cue:103:6 } q: (int){ int } } incomplete7: (struct){ p: (_|_){ // [incomplete] embed.incomplete7.p: non-concrete value int in operand to +: // ./in.cue:106:6 // ./in.cue:107:6 // ./in.cue:108:3 } q: (int){ int } } } mixedFieldsSuccess: (struct){ a: (struct){ X: (int){ 1 } foo: (int){ 1 } } b: (struct){ #Def: (#struct){ X: (int){ 1 } foo: (int){ 1 } } x: (#struct){ X: (int){ 1 } foo: (int){ 1 } } } c: (struct){ #Def: (#struct){ X: (int){ int } foo: (int){ int } } x: (#struct){ X: (int){ 1 } foo: (int){ 1 } } } } fieldMismatch: (_|_){ // [eval] a: (_|_){ // [eval] fieldMismatch.a: cannot combine regular field "x" with 2: // ./in.cue:152:7 // ./in.cue:150:3 x: (int){ 3 } } } noStackOverflowStructCycle: (_|_){ // [structural cycle] #list: (_|_){ // [structural cycle] noStackOverflowStructCycle.#list.tail: structural cycle } list: (_|_){ // [structural cycle] noStackOverflowStructCycle.list.tail: structural cycle } } provideIncompleteSuccess: (_|_){ // [eval] t1: (struct){ #a: (_|_){ // [incomplete] provideIncompleteSuccess.t1.#a: incomplete bool: bool: // ./in.cue:185:7 b: (bool){ bool } } x: (#struct){ c: (int){ 4 } b: (bool){ true } } y: (#struct){ c: (int){ 4 } b: (bool){ true } } } t2: (_|_){ // [eval] #a: (#struct){ c: (int){ 4 } b: (bool){ true } } #c: (#struct){ } a: (_|_){ // [eval] c: (_|_){ // [eval] d: (_|_){ // [eval] provideIncompleteSuccess.t2.a.c.d: field not allowed: // ./in.cue:200:7 // ./in.cue:202:4 // ./in.cue:203:8 // ./in.cue:208:7 } } b: (bool){ true } } } } voidArcs: (struct){ scopes: (struct){ x: (int){ 1 } a: (struct){ y: (int){ 2 } b: (int){ 1 } c: (struct){ d: (int){ 1 } } e: (int){ 2 } f: (struct){ g: (int){ 2 } } } } drop: (struct){ x: (int){ 1 } a: (struct){ y: (int){ 2 } } } } cyclicError: (struct){ a: (_|_){ // [cycle] cycle error } c: (struct){ } } midwayReferences: (struct){ a: (struct){ x: (struct){ y: (struct){ z: (struct){ a: (int){ 1 } b: (int){ 2 } } } } } b: (struct){ y: (struct){ z: (struct){ a: (int){ 1 } b: (int){ 2 } } } } c: (struct){ z: (struct){ a: (int){ 1 } b: (int){ 2 } } } d: (struct){ a: (int){ 1 } b: (int){ 2 } } } closedCheck: (struct){ success1: (struct){ a: (struct){ b: (struct){ c: (#struct){ d: (string){ "d" } e: (string){ "ok" } } } } #D: (_|_){ // [incomplete] closedCheck.success1.#D: non-concrete value string in operand to !=: // ./in.cue:280:6 // ./in.cue:279:6 d: (string){ string } } } success2: (struct){ a: (struct){ b: (struct){ c: (#struct){ d: (string){ "d" } foobar: (string){ "ok" } } } } #D: (_|_){ // [incomplete] closedCheck.success2.#D: non-concrete value string in operand to !=: // ./in.cue:296:6 // ./in.cue:295:6 d: (string){ string } } } success3: (struct){ a: (struct){ b: (struct){ c: (#struct){ d: (string){ "d" } e: (string){ "ok" } } } } #D: (#struct){ d: (string){ string } e: (_|_){ // [incomplete] closedCheck.success3.#D.e: non-concrete value string in operand to !=: // ./in.cue:313:7 // ./in.cue:311:6 } } } } emptyComprehensionIncomplete: (struct){ a: (struct){ } b: (_|_){ // [incomplete] emptyComprehensionIncomplete.b: undefined field: b: // ./in.cue:329:8 } } voidEliminationSuccess: (struct){ t1: (struct){ } t2: (struct){ components: (struct){ sinks: (struct){ blah: (#struct){ kind: (string){ "source" } configuration: (#struct){ } } } #C: (#struct){ kind: (string){ string } configuration: (#struct){ } } } } derefRef1: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (struct){ e: (bool){ bool } f: (_|_){ // [incomplete] voidEliminationSuccess.derefRef1.E.f: operand e of '!' not concrete (was bool): // ./in.cue:386:7 } } } derefRef2: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (#struct){ e: (bool){ bool } f: (_|_){ // [incomplete] voidEliminationSuccess.derefRef2.E.f: operand e of '!' not concrete (was bool): // ./in.cue:402:7 } } #F: (#struct){ e: (bool){ bool } f: (_|_){ // [incomplete] voidEliminationSuccess.derefRef2.#F.f: operand e of '!' not concrete (was bool): // ./in.cue:402:7 } } } derefDisj1: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (_|_){ // [incomplete] voidEliminationSuccess.derefDisj1.E: 2 errors in empty disjunction:: // ./in.cue:407:28 // voidEliminationSuccess.derefDisj1.E.f: operand e of '!' not concrete (was bool): // ./in.cue:417:7 // voidEliminationSuccess.derefDisj1.E.h: operand g of '!' not concrete (was bool): // ./in.cue:420:7 g: (bool){ bool } h: (_|_){ // [incomplete] voidEliminationSuccess.derefDisj1.E.h: operand g of '!' not concrete (was bool): // ./in.cue:420:7 } } } derefDisj2: (struct){ a: (struct){ b: (struct){ c: (struct){ } } } E: (_|_){ // [incomplete] voidEliminationSuccess.derefDisj2.E: 2 errors in empty disjunction:: // ./in.cue:425:28 // voidEliminationSuccess.derefDisj2.E.f: operand e of '!' not concrete (was bool): // ./in.cue:435:7 // voidEliminationSuccess.derefDisj2.E.h: operand g of '!' not concrete (was bool): // ./in.cue:438:7 g: (bool){ bool } h: (_|_){ // [incomplete] voidEliminationSuccess.derefDisj2.E.h: operand g of '!' not concrete (was bool): // ./in.cue:438:7 } } } bulk1: (struct){ a: (struct){ b: (struct){ c: (struct){ e: (string){ string } } d: (string){ string } } } } opt1: (struct){ a: (struct){ b: (struct){ c: (struct){ e: (string){ string } } d: (string){ string } } } } noCycle1: (struct){ _x: (struct){ } a: (struct){ c: (struct){ h: (string){ "stream" } } b: (struct){ } } } noCycle2: (struct){ a: (struct){ c: (struct){ h: (string){ "stream" } } b: (struct){ } } _x: (struct){ } } drop1: (struct){ t: (struct){ #ok: (bool){ |(*(bool){ true }, (bool){ bool }) } x: (int){ int } } s: (struct){ #ok: (bool){ false } } } } voidLookup: (struct){ a: (struct){ x: (struct){ z: (_|_){ // [incomplete] voidLookup.a.x.z: undefined field: void: // ./in.cue:495:17 } c: (_|_){ // [incomplete] voidLookup.a.x.z: undefined field: void: // ./in.cue:495:17 } } y: (struct){ c: (_){ _ } z: (struct){ } } } } topElimination: (struct){ a: (int){ int } x: (_|_){ // [incomplete] topElimination.x: non-concrete value int in operand to +: // ./in.cue:523:6 // ./in.cue:520:5 } } explicitDefaultError: (_|_){ // [incomplete] explicitDefaultError: non-concrete value string in operand to !=: // ./in.cue:545:5 // ./in.cue:543:5 a: (string){ string } } allArcsSuccess: (struct){ p1: (struct){ x: (struct){ } y: (struct){ } } p2: (struct){ y: (struct){ } x: (struct){ } } } structShare: (_|_){ // [eval] ok1: (struct){ a: (struct){ d: (struct){ e: (bool){ true } } } E: (struct){ } } err1: (_|_){ // [eval] x: (_|_){ // [eval] #E: (#struct){ } d: (_|_){ // [eval] e: (_|_){ // [eval] structShare.err1.x.d.e: field not allowed: // ./in.cue:588:15 // ./in.cue:589:9 // ./in.cue:590:2 // ./in.cue:591:9 } } } } } unity: (struct){ success1: (struct){ #Config: (#struct){ name: (string){ string } type: (string){ string } } #AnyConfig: (#struct){ name: (string){ string } type: (string){ string } } #Env: (#struct){ name: (string){ string } configurations: (#struct){ } } envs: (struct){ e1: (#struct){ name: (string){ string } configurations: (#struct){ c1: (#struct){ name: (string){ string } type: (string){ "foo" } } } } } } } issue1759: (struct){ _ports_map: (struct){ a: (struct){ port: (string){ "80" } } } port: (string){ "80" } } arcAlignment: (struct){ t1: (struct){ } } letPushdown: (struct){ _c: (struct){ y: (int){ 1 } } a: (struct){ let x#1multi = 〈1;v〉 } } nestedWithEmbeddingOK: (struct){ c: (#list){ 0: (int){ 1 } } a: (struct){ x: (int){ 1 } } } nestedWithDynamicFieldOK: (struct){ _c: (struct){ y: (int){ 1 } } a: (_|_){ // [cycle] nestedWithDynamicFieldOK.a: circular dependency in evaluation of conditionals: "\(〈1;k〉)" changed after evaluation: // ./issue2113.cue:19:7 } } errorPropagation: (_|_){ // [incomplete] errorPropagation: undefined field: env2: // ./issue2113.cue:30:19 deployment: (_|_){ // [incomplete] errorPropagation: undefined field: env2: // ./issue2113.cue:30:19 elem: (struct){ x2: (int){ 2 } } } } issue2131: (struct){ tests: (struct){ windows: (struct){ eg1: (struct){ in: (string){ "c:\\d" } out: (string){ "test" } } eg2: (struct){ in: (string){ "c:\\test" } out: (string){ "test" } } eg3: (struct){ in: (string){ "c:\\test\\d" } out: (string){ "test" } } } } } voidErrorIncomplete: (struct){ #Schema: (#struct){ } root: (#struct){ } } issue3533: (struct){ #ObjectMeta: (#struct){ namespace?: (string){ string } } out: (struct){ metadata: (#struct){ namespace: (string){ |(*(string){ "default" }, (string){ string }) } } } } issue3535: (_|_){ // [eval] hidden: (struct){ #X: (#struct){ kind: (string){ string } output: (#struct){ } } foo: (#struct){ kind: (string){ "foo" } output: (#struct){ } _hidden: (struct){ } } } regular: (_|_){ // [eval] #X: (#struct){ kind: (string){ string } output: (#struct){ } } foo: (_|_){ // [eval] kind: (string){ "foo" } output: (#struct){ } regular: (_|_){ // [eval] issue3535.regular.foo.regular: field not allowed: // ./issue3535.cue:15:6 // ./issue3535.cue:19:7 // ./issue3535.cue:19:12 // ./issue3535.cue:21:3 // ./issue3535.cue:22:4 // ./issue3535.cue:25:7 } } } def: (struct){ #X: (#struct){ kind: (string){ string } output: (#struct){ } } foo: (#struct){ kind: (string){ "foo" } output: (#struct){ } #def: (#struct){ } } } } issue3621: (struct){ reduced: (struct){ t1: (struct){ a: (string){ "Foo" } b1: (struct){ b2: (struct){ b3: (string){ "Foo" } } } } t2: (struct){ outer: (struct){ b: (string){ "Foo" } } inner: (struct){ inner2: (struct){ name: (string){ "Foo" } } } } } full: (struct){ hello: (string){ "world" } outer: (struct){ outer2: (struct){ bar: (string){ "Employees" } name: (string){ "outer2" } } } inner: (struct){ inner2: (struct){ name: (string){ "Employees" } description: (string){ "All employees" } privacy: (string){ "secret" } create_default: (bool){ false } } } } } unifyDynamicReflectSuccess: (struct){ X: (struct){ X: (struct){ x: (struct){ y: (struct){ } } } } foo: (struct){ X: (struct){ x: (struct){ y: (struct){ } } } Y: (string){ "{\"x\":{\"y\":{}}}" } } } } -- out/compile -- --- in.cue { linkChildren: { w: 1 v: { x: 1 if true { y: 1 if true { z: 1 rw: 〈3;w〉 rx: 〈2;x〉 ry: 〈1;y〉 rz: 〈0;z〉 n1a: { na: [ 〈5;w〉, 〈4;x〉, 〈3;y〉, 〈2;z〉, ] } n2a: { n1a: { na: [ 〈6;w〉, 〈5;x〉, 〈4;y〉, 〈3;z〉, ] } } n2z: { n1z: { nz: 〈2;z〉 } } } } } } fail: { a: { if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { b: 1 } } } embed: { fail1: 〈0;#C1〉 #C1: { if false { p: _ } } fail1: { p: "foo" } success2: 〈0;#C2〉 #C2: { if true { p: _ } } success2: { p: "foo" } success3: 〈0;#C3〉 #C3: {} success3: { if false { p: { q: 1 } } } success4: { #X: { y: string } x: { y: string } x: { for _, _ in [ "iter-once", ] { 〈3;#X〉 if false { y: "foo" } } } } fail4: 〈0;#C4〉 #C4: {} fail4: { if true { p: { q: 1 } } } incomplete5: { a: bool if 〈0;a〉 { p: { q: 1 } } } incomplete6: { if false { p: 1 } p: (〈0;q〉 + 1) q: int } incomplete7: { p: (〈0;q〉 + 1) q: int if false { q: 1 } } } mixedFieldsSuccess: { a: { for _, s in [ "foo", ] { "\(〈1;s〉)": 1 X: 1 } } b: { #Def: { for _, s in [ "foo", ] { "\(〈1;s〉)": 1 X: 1 } } } b: { x: 〈1;b〉.#Def } b: { x: { X: _ } } b: { x: { foo: _ } } c: { #Def: { X: int foo: int } } c: { x: 〈1;c〉.#Def } c: { x: { for _, s in [ "foo", ] { "\(〈1;s〉)": 1 X: 1 } } } } fieldMismatch: { a: { 2 if true { x: 3 } } } noStackOverflowStructCycle: { #list: { tail: 〈1;#list〉 if (〈0;tail〉 != null) { sum: 〈1;tail〉.sum } } list: { tail: 〈1;list〉 if (〈0;tail〉 != null) { sum: 〈1;tail〉.sum } } } provideIncompleteSuccess: { t1: { #a: { if 〈0;b〉 { c: 4 } b: bool } x: ((〈0;#a〉 & { b: true }) & { c: 4 }) y: 〈0;x〉 } t2: { #a: { if 〈0;b〉 { c: 4 } b: true } #c: {} a: { if 〈0;b〉 { c: { d: 4 } } b: true c: 〈1;#c〉 } } } voidArcs: { scopes: { x: 1 a: { y: 2 if true { b: 〈2;x〉 c: { d: 〈3;x〉 } e: 〈1;y〉 f: { g: 〈2;y〉 } } } } drop: { x: 1 a: { y: 2 if false { b: 〈2;x〉 c: { d: 〈3;x〉 } e: 〈1;y〉 f: { g: 〈2;y〉 } } } } } cyclicError: { a: { x: bool y: bool if 〈1;a〉.x { y: true } if 〈1;a〉.y { x: true } b: {} } c: 〈0;a〉.b } midwayReferences: { a: { for i, j in { a: 1 b: 2 } { x: { y: { z: { 〈4;i〉: 〈4;j〉 } } } } x: { y: {} } } b: 〈0;a〉.x c: 〈0;a〉.x.y d: 〈0;a〉.x.y.z } closedCheck: { success1: { a: { b: { [string]: 〈2;#D〉 } } #D: { d: string if (〈0;d〉 != "c") { e: string } } a: { b: { c: { d: "d" e: "ok" } } } } } closedCheck: { success2: { a: { b: { [string]: 〈2;#D〉 } } #D: { d: string if (〈0;d〉 != "c") { ("foo" + "bar"): string } } a: { b: { c: { d: "d" foobar: "ok" } } } } } closedCheck: { success3: { a: { b: { [string]: 〈2;#D〉 } } #D: { d: string e: { if (〈1;d〉 != "c") { string } } } a: { b: { c: { d: "d" e: "ok" } } } } } emptyComprehensionIncomplete: { a: {} b: { if 〈1;a〉.b {} } } voidEliminationSuccess: { t1: { [string]: { b: bool if !〈0;b〉 {} } if false { a: { b: true } } } } voidEliminationSuccess: { t2: { components: { sinks: { [string]: (〈1;#C〉 & { kind: string configuration: { if (〈1;kind〉 != "source") { inputs: { required: true } } } }) } #C: { kind: string configuration: { [string]: { required: bool if !〈0;required〉 { common: bool } } } } } components: { sinks: { blah: { kind: "source" } } } } } voidEliminationSuccess: { derefRef1: { a: { [string]: { c: { [string]: 〈3;E〉 } } } a: { b: { c: { if false { d: { e: true } } } } } E: { e: bool f: !〈0;e〉 } } } voidEliminationSuccess: { derefRef2: { a: { [string]: { c: { [string]: 〈3;E〉 } } } a: { b: { c: { if false { d: { e: true } } } } } E: 〈0;#F〉 #F: { e: bool f: !〈0;e〉 } } } voidEliminationSuccess: { derefDisj1: { a: { [string]: { c: { [string]: 〈3;E〉 } } } a: { b: { c: { if false { d: { e: true } } } } } E: ({ e: bool f: !〈0;e〉 }|{ g: bool h: !〈0;g〉 }) } } voidEliminationSuccess: { derefDisj2: { a: { [string]: { c: { [string]: (〈3;E〉 & 〈3;E〉) } } } a: { b: { c: { if false { d: { e: true } } } } } E: ({ e: bool f: !〈0;e〉 }|{ g: bool h: !〈0;g〉 }) } } voidEliminationSuccess: { bulk1: { a: { b: {} } a: { [string]: { c: { e: string if false { e: "" } } d: 〈0;c〉.e } } } } voidEliminationSuccess: { opt1: { a: { b: {} } a: { b?: { c: { e: string if false { e: "" } } d: 〈0;c〉.e } } } } voidEliminationSuccess: { noCycle1: { _x: 〈0;a〉.b a: { c: { h: "stream" } b: { if (〈1;c〉.g != _|_(explicit error (_|_ literal) in source)) {} } c: { if false { g: _ } } } } } voidEliminationSuccess: { noCycle2: { a: { c: { h: "stream" } b: { if (〈1;c〉.g != _|_(explicit error (_|_ literal) in source)) {} } c: { if false { g: _ } } } _x: 〈0;a〉.b } } voidLookup: { a: { x: { z: 〈2;a〉.y.z.void } } a: { y: { c: _ z: {} } } a: { [string]: { c: { for k, v in 〈1;z〉 { 〈1;k〉: null } } z: { if false { err: {} } } } } } topElimination: { a: int _ if true { x: (〈1;a〉 + 1) } } voidEliminationSuccess: { drop1: { t: { #ok: (*true|bool) if 〈0;#ok〉 { x: int } } s: (〈0;t〉 & { #ok: false }) } } explicitDefaultError: { a: (string|*_|_(explicit error (_|_ literal) in source)) if (〈0;a〉 != "") {} } allArcsSuccess: { p1: { x: { for k, _ in 〈1;y〉 { 〈1;k〉: null } } y: { if false { x: {} } } } } allArcsSuccess: { p2: { y: { if false { x: {} } } x: { for k, _ in 〈1;y〉 { 〈1;k〉: null } } } } structShare: { ok1: { a: { [string]: 〈1;E〉 } E: {} a: { if true { d: { e: true } } } } } structShare: { err1: { x: { [string]: 〈1;x〉.#E } x: { #E: {} } if true { x: { d: { e: true } } } } } } --- issue1759.cue { unity: { success1: { #Config: { name: string type: string } #AnyConfig: { 〈1;#Config〉 ... } #Env: { name: string configurations: { [string]: 〈2;#AnyConfig〉 } } envs: { e1: (〈1;#Env〉 & { configurations: { c1: 〈3;#Config〉 } }) } envs: { [string]: { configurations: { [string]: { type: "foo" if (〈0;type〉 == "terraform") { backend: { type: "s3" } } } } } } } } issue1759: { _ports_map: {} if (len(〈0;_ports_map〉) > 0) { port: 〈1;_ports_map〉.a.port } if true { _ports_map: { a: { port: "80" } } } } arcAlignment: { t1: { [string]: { if true {} } if false { c: _ } } } } --- issue2111.cue { letPushdown: { _c: { y: 1 } a: { for k, v in 〈1;_c〉 { let x#1multi = 〈1;v〉 if (〈0;let x#1〉 != _|_(explicit error (_|_ literal) in source)) {} } } } } --- issue2113.cue { nestedWithEmbeddingOK: { c: [ 1, ] a: { for k, v in 〈1;c〉 { { x: 1 } if (〈3;a〉.x != _|_(explicit error (_|_ literal) in source)) {} } } } nestedWithDynamicFieldOK: { _c: { y: 1 } a: { for k, v in 〈1;_c〉 { if (〈0;("\(〈1;k〉)")〉 != _|_(explicit error (_|_ literal) in source)) {} "\(〈1;k〉)": 1 } } } errorPropagation: { deployment: _ for k, v in 〈0;deployment〉 { for k1, v2 in 〈1;v〉.env2 { deployment: { 〈4;k〉: { x1: 1 } } } } for _, id in [ "elem", ] { deployment: { 〈2;id〉: { x2: 2 } } } } } --- issue2131.cue { issue2131: { tests: { windows: { eg1: { in: "c:\\d" } eg2: { in: "c:\\test" } eg3: { in: "c:\\test\\d" } } for os, examples in 〈1;tests〉 for k, v in 〈0;examples〉 { 〈2;os〉: { 〈2;k〉: { out: "test" } } } } } } --- issue2208.cue { voidErrorIncomplete: { #Schema: { [string]: { required: bool if !〈0;required〉 {} } } root: 〈0;#Schema〉 root: { if false { child: { required: false } } } } } --- issue3533.cue { issue3533: { #ObjectMeta: { namespace?: string } out: { for i, _ in [ "iter-once", ] { metadata: 〈3;#ObjectMeta〉 if false { metadata: { namespace: "foo" } } } } out: { metadata: { namespace: (*"default"|string) } } } } --- issue3535.cue { issue3535: { hidden: { #X: { kind: string output: {} } foo: (〈0;#X〉 & { kind: string if (〈0;kind〉 == "foo") { _hidden: {} } }) foo: { kind: "foo" } } } issue3535: { regular: { #X: { kind: string output: {} } foo: (〈0;#X〉 & { kind: string if (〈0;kind〉 == "foo") { regular: {} } }) foo: { kind: "foo" } } } issue3535: { def: { #X: { kind: string output: {} } foo: (〈0;#X〉 & { kind: string if (〈0;kind〉 == "foo") { #def: {} } }) foo: { kind: "foo" } } } } --- issue3621.cue { issue3621: { reduced: { t1: { if true { a: 〈0;b1〉.b2.b3 b1: { b2: { b3: "Foo" } } } } } } issue3621: { reduced: { t2: { outer: {} if true { inner: { inner2: { name: "Foo" } } outer: { b: 〈1;inner〉.inner2.name } } } } } issue3621: { full: { hello: "world" outer: { [string]: { name: 〈1;-〉 } } if true { inner: { inner2: { name: "Employees" description: "All employees" privacy: "secret" create_default: false } } outer: { outer2: { bar: 〈2;inner〉.inner2.name } } } } } } --- reflect.cue { unifyDynamicReflectSuccess: { for _, s in [ "foo", ] { X: { ... } "\(〈1;s〉)": { X: { ... } Y: 〈import;"encoding/json"〉.Marshal(〈0;X〉) } } [string]: { X: { if true { x: { y: {} } } } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/000077500000000000000000000000001474664451600201645ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/cycle/015_reference_across_tuples_and_back.txtar000066400000000000000000000013701474664451600303440ustar00rootroot00000000000000#name: reference across tuples and back #evalPartial -- in.cue -- a: {c: b.e, d: b.f} b: {e: 3, f: a.c} -- out/def -- a: { c: 3 d: 3 } b: { e: 3 f: 3 } -- out/export -- a: { c: 3 d: 3 } b: { e: 3 f: 3 } -- out/yaml -- a: c: 3 d: 3 b: e: 3 f: 3 -- out/json -- {"a":{"c":3,"d":3},"b":{"e":3,"f":3}} -- out/legacy-debug -- <0>{a: <1>{c: 3, d: 3}, b: <2>{e: 3, f: 3}} -- out/compile -- --- in.cue { a: { c: 〈1;b〉.e d: 〈1;b〉.f } b: { e: 3 f: 〈1;a〉.c } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 1 Allocs: 6 Retain: 8 Unifications: 7 Conjuncts: 12 Disjuncts: 12 -- out/eval -- (struct){ a: (struct){ c: (int){ 3 } d: (int){ 3 } } b: (struct){ e: (int){ 3 } f: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/cycle/021_delayed_constraint_failure.txtar000066400000000000000000000022171474664451600272160ustar00rootroot00000000000000#name: delayed constraint failure #evalPartial -- in.cue -- a: b - 100 // Okay to have no error here, as long as there is an error with b. b: a + 110 b: 200 x: 100 x: x + 1 -- out/def -- x: _|_ // conflicting values 100 and 101 a: _|_ // conflicting values 210 and 200 b: _|_ // conflicting values 210 and 200 -- out/legacy-debug -- <0>{x: _|_((100 & 101):conflicting values 100 and 101), a: _|_((210 & 200):conflicting values 210 and 200), b: _|_((210 & 200):conflicting values 210 and 200)} -- out/compile -- --- in.cue { a: (〈0;b〉 - 100) b: (〈0;a〉 + 110) b: 200 x: 100 x: (〈0;x〉 + 1) } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 1 Allocs: 3 Retain: 1 Unifications: 4 Conjuncts: 5 Disjuncts: 4 -- out/eval -- Errors: b: conflicting values 210 and 200: ./in.cue:2:4 ./in.cue:3:4 x: conflicting values 101 and 100: ./in.cue:5:4 ./in.cue:6:4 Result: (_|_){ // [eval] a: (int){ 100 } b: (_|_){ // [eval] b: conflicting values 210 and 200: // ./in.cue:2:4 // ./in.cue:3:4 } x: (_|_){ // [eval] x: conflicting values 101 and 100: // ./in.cue:5:4 // ./in.cue:6:4 } } cue-lang-cue-db9cc73/cue/testdata/cycle/023_reentrance.txtar000066400000000000000000000125221474664451600237640ustar00rootroot00000000000000#name: reentrance #evalFull -- in.cue -- // This indirection is needed to avoid binding references to fib // within fib to the instantiated version. fibRec: {nn: int, out: (fib & {n: nn}).out} fib: { n: int if n >= 2 { out: (fibRec & {nn: n - 2}).out + (fibRec & {nn: n - 1}).out } if n < 2 { out: n } } fib1: (fib & {n: 1}).out // MAY NOT be an error fib2: (fib & {n: 2}).out // MAY be an error fib3: (fib & {n: 3}).out // SHOULD be an error fib7: (fib & {n: 7}).out // Error fib12: (fib & {n: 12}).out // Error -- out/legacy-debug -- <0>{fibRec: <1>{nn: int, out: (<2>.fib & <3>{n: <4>.nn}).out}, fib: <5>{n: int if (<6>.n >= 2) yield <7>{out: ((<2>.fibRec & <8>{nn: (<6>.n - 2)}).out + (<2>.fibRec & <9>{nn: (<6>.n - 1)}).out)}, if (<6>.n < 2) yield <10>{out: <6>.n}}, fib2: 1, fib7: 13, fib12: 144} -- out/compile -- --- in.cue { fibRec: { nn: int out: (〈1;fib〉 & { n: 〈1;nn〉 }).out } fib: { n: int if (〈0;n〉 >= 2) { out: ((〈2;fibRec〉 & { nn: (〈2;n〉 - 2) }).out + (〈2;fibRec〉 & { nn: (〈2;n〉 - 1) }).out) } if (〈0;n〉 < 2) { out: 〈1;n〉 } } fib1: (〈0;fib〉 & { n: 1 }).out fib2: (〈0;fib〉 & { n: 2 }).out fib3: (〈0;fib〉 & { n: 3 }).out fib7: (〈0;fib〉 & { n: 7 }).out fib12: (〈0;fib〉 & { n: 12 }).out } -- out/evalalpha/stats -- Leaks: 70 Freed: 0 Reused: 0 Allocs: 70 Retain: 0 Unifications: 62 Conjuncts: 224 Disjuncts: 0 -- out/evalalpha -- Errors: structural cycle: ./in.cue:3:25 Result: (_|_){ // [structural cycle] fibRec: (struct){ nn: (int){ int } out: (_|_){ // [incomplete] non-concrete value int in operand to >=: // ./in.cue:7:5 // ./in.cue:3:35 // ./in.cue:5:5 // non-concrete value int in operand to <: // ./in.cue:10:5 // ./in.cue:3:35 // ./in.cue:5:5 } } fib: (_|_){ // [incomplete] fib: non-concrete value int in operand to >=: // ./in.cue:7:5 // ./in.cue:5:5 // fib: non-concrete value int in operand to <: // ./in.cue:10:5 // ./in.cue:5:5 n: (int){ int } } fib1: (int){ 1 } fib2: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 } fib3: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 } fib7: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 } fib12: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 16 -Freed: 180 -Reused: 170 -Allocs: 26 -Retain: 148 +Leaks: 70 +Freed: 0 +Reused: 0 +Allocs: 70 +Retain: 0 -Unifications: 196 -Conjuncts: 464 -Disjuncts: 268 +Unifications: 62 +Conjuncts: 224 +Disjuncts: 0 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,10 +1,6 @@ Errors: structural cycle: ./in.cue:3:25 -structural cycle: - ./in.cue:8:9 -structural cycle: - ./in.cue:8:38 Result: (_|_){ @@ -32,27 +28,20 @@ n: (int){ int } } fib1: (int){ 1 } - fib2: (int){ 1 } + fib2: (_|_){ + // [structural cycle] structural cycle: + // ./in.cue:3:25 + } fib3: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 - // structural cycle: - // ./in.cue:8:38 } fib7: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 - // structural cycle: - // ./in.cue:8:9 - // structural cycle: - // ./in.cue:8:38 } fib12: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 - // structural cycle: - // ./in.cue:8:9 - // structural cycle: - // ./in.cue:8:38 } } -- diff/todo/p3 -- Note that it is okay for fib2 to fail. -- out/eval/stats -- Leaks: 16 Freed: 180 Reused: 170 Allocs: 26 Retain: 148 Unifications: 196 Conjuncts: 464 Disjuncts: 268 -- out/eval -- Errors: structural cycle: ./in.cue:3:25 structural cycle: ./in.cue:8:9 structural cycle: ./in.cue:8:38 Result: (_|_){ // [structural cycle] fibRec: (struct){ nn: (int){ int } out: (_|_){ // [incomplete] non-concrete value int in operand to >=: // ./in.cue:7:5 // ./in.cue:3:35 // ./in.cue:5:5 // non-concrete value int in operand to <: // ./in.cue:10:5 // ./in.cue:3:35 // ./in.cue:5:5 } } fib: (_|_){ // [incomplete] fib: non-concrete value int in operand to >=: // ./in.cue:7:5 // ./in.cue:5:5 // fib: non-concrete value int in operand to <: // ./in.cue:10:5 // ./in.cue:5:5 n: (int){ int } } fib1: (int){ 1 } fib2: (int){ 1 } fib3: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 // structural cycle: // ./in.cue:8:38 } fib7: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 // structural cycle: // ./in.cue:8:9 // structural cycle: // ./in.cue:8:38 } fib12: (_|_){ // [structural cycle] structural cycle: // ./in.cue:3:25 // structural cycle: // ./in.cue:8:9 // structural cycle: // ./in.cue:8:38 } } -- diff/todo/p2 -- Elimination of unnecessary, but potentially useful, errors. cue-lang-cue-db9cc73/cue/testdata/cycle/025_cannot_resolve_references_that_would_be_ambiguous.txtar000066400000000000000000000047551474664451600340460ustar00rootroot00000000000000#name: cannot resolve references that would be ambiguous #evalFull -- in.cue -- a1: *0 | 1 a1: a3 - a2 a2: *0 | 1 a2: a3 - a1 a3: 1 b1: (*0 | 1) & b2 b2: (0 | *1) & b1 c1: (*{a: 1} | {b: 1}) & c2 c2: (*{a: 2} | {b: 2}) & c1 -- out/def -- a1: (*0 | 1) & a3-a2 a3: 1 a2: (*0 | 1) & a3-a1 b1: (*0 | 1) & b2 b2: (0 | *1) & b1 c1: (*{ a: 1 } | { b: 1 }) & c2 c2: (*{ a: 2 } | { b: 2 }) & c1 -- out/legacy-debug -- <0>{a1: ((*0 | 1) & (<1>.a3 - <1>.a2)), a3: 1, a2: ((*0 | 1) & (<1>.a3 - <1>.a1)), b1: (0 | 1), b2: (0 | 1), c1: (<2>{a: 1, b: 2} | <3>{a: 2, b: 1}), c2: (<4>{a: 2, b: 1} | <5>{a: 1, b: 2})} -- out/compile -- --- in.cue { a1: (*0|1) a1: (〈0;a3〉 - 〈0;a2〉) a2: (*0|1) a2: (〈0;a3〉 - 〈0;a1〉) a3: 1 b1: ((*0|1) & 〈0;b2〉) b2: ((0|*1) & 〈0;b1〉) c1: ((*{ a: 1 }|{ b: 1 }) & 〈0;c2〉) c2: ((*{ a: 2 }|{ b: 2 }) & 〈0;c1〉) } -- out/eval/stats -- Leaks: 0 Freed: 52 Reused: 43 Allocs: 9 Retain: 19 Unifications: 24 Conjuncts: 80 Disjuncts: 52 -- out/evalalpha -- (struct){ a1: (_|_){ // [cycle] cycle error: // ./in.cue:4:5 } a2: (_|_){ // [cycle] cycle error: // ./in.cue:4:5 } a3: (int){ 1 } b1: (int){ |((int){ 0 }, (int){ 1 }) } b2: (int){ |((int){ 0 }, (int){ 1 }) } c1: (struct){ |((struct){ a: (int){ 1 } b: (int){ 2 } }, (struct){ b: (int){ 1 } a: (int){ 2 } }) } c2: (struct){ |((struct){ a: (int){ 2 } b: (int){ 1 } }, (struct){ b: (int){ 2 } a: (int){ 1 } }) } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,12 @@ (struct){ a1: (_|_){ // [cycle] cycle error: - // ./in.cue:2:5 - } - a2: (int){ 1 } + // ./in.cue:4:5 + } + a2: (_|_){ + // [cycle] cycle error: + // ./in.cue:4:5 + } a3: (int){ 1 } b1: (int){ |((int){ 0 }, (int){ 1 }) } b2: (int){ |((int){ 0 }, (int){ 1 }) } -- diff/explanation -- a2: cyclic error reporting is now reported at both nodes on cycle, which is good. -- out/eval -- (struct){ a1: (_|_){ // [cycle] cycle error: // ./in.cue:2:5 } a2: (int){ 1 } a3: (int){ 1 } b1: (int){ |((int){ 0 }, (int){ 1 }) } b2: (int){ |((int){ 0 }, (int){ 1 }) } c1: (struct){ |((struct){ a: (int){ 1 } b: (int){ 2 } }, (struct){ b: (int){ 1 } a: (int){ 2 } }) } c2: (struct){ |((struct){ a: (int){ 2 } b: (int){ 1 } }, (struct){ b: (int){ 2 } a: (int){ 1 } }) } } cue-lang-cue-db9cc73/cue/testdata/cycle/049_self-reference_cycles_conflicts_with_strings.txtar000066400000000000000000000015421474664451600327450ustar00rootroot00000000000000#name: self-reference cycles conflicts with strings #evalPartial -- in.cue -- a: { x: y + "?" y: x + "!" } a: x: "hey" -- out/def -- a: { x: _|_ // conflicting values "hey!?" and "hey" y: "hey!" } -- out/legacy-debug -- <0>{a: <1>{x: _|_(("hey!?" & "hey"):conflicting values "hey!?" and "hey"), y: "hey!"}} -- out/compile -- --- in.cue { a: { x: (〈0;y〉 + "?") y: (〈0;x〉 + "!") } a: { x: "hey" } } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 0 Allocs: 4 Retain: 1 Unifications: 4 Conjuncts: 5 Disjuncts: 5 -- out/eval -- Errors: a.x: conflicting values "hey!?" and "hey": ./in.cue:2:5 ./in.cue:5:7 Result: (_|_){ // [eval] a: (_|_){ // [eval] x: (_|_){ // [eval] a.x: conflicting values "hey!?" and "hey": // ./in.cue:2:5 // ./in.cue:5:7 } y: (string){ "hey!" } } } cue-lang-cue-db9cc73/cue/testdata/cycle/050_resolved_self-reference_cycles_with_disjunctions.txtar000066400000000000000000000023101474664451600336110ustar00rootroot00000000000000#name: resolved self-reference cycles with disjunctions #evalPartial -- in.cue -- a: b & {x: 1} | {y: 1} // {x:1,y:3,z:2} | {y:1} b: {x: 2} | c & {z: 2} // {x:2} | {x:1,y:3,z:2} c: a & {y: 3} | {z: 3} // {x:1,y:3,z:2} | {z:3} -- out/def -- a: b & { x: 1 } | { y: 1 } b: { x: 2 } | c & { z: 2 } c: a & { y: 3 } | { z: 3 } -- out/legacy-debug -- <0>{a: (<1>{x: 1, y: 3, z: 2} | <2>{y: 1}), b: (<3>{x: 2} | <4>{x: 1, y: 3, z: 2}), c: (<5>{x: 1, y: 3, z: 2} | <6>{z: 3})} -- out/compile -- --- in.cue { a: ((〈0;b〉 & { x: 1 })|{ y: 1 }) b: ({ x: 2 }|(〈0;c〉 & { z: 2 })) c: ((〈0;a〉 & { y: 3 })|{ z: 3 }) } -- out/eval/stats -- Leaks: 0 Freed: 43 Reused: 32 Allocs: 11 Retain: 0 Unifications: 25 Conjuncts: 64 Disjuncts: 43 -- out/eval -- (struct){ a: (struct){ |((struct){ x: (int){ 1 } z: (int){ 2 } y: (int){ 3 } }, (struct){ y: (int){ 1 } }) } b: (struct){ |((struct){ x: (int){ 2 } }, (struct){ z: (int){ 2 } y: (int){ 3 } x: (int){ 1 } }) } c: (struct){ |((struct){ y: (int){ 3 } x: (int){ 1 } z: (int){ 2 } }, (struct){ z: (int){ 3 } }) } } cue-lang-cue-db9cc73/cue/testdata/cycle/051_resolved_self-reference_cycles_with_disjunction.txtar000066400000000000000000000223461474664451600334420ustar00rootroot00000000000000#name: resolved self-reference cycles with disjunction #evalPartial // TODO(cycle) // // Some of these examples used to work, but the changes corresponding to this // addition, it ceased to do so. Fixing these cycle issues seemed more // important than keeping this esoteric case working, which was already broken // in the last release anyway. // // Reproducer of underlying problem. Still works, but triggers unexpected // condition. // // xb1: xb2 // xb2: xb3 // xb3: xb2 + 0 -- in.cue -- // The second disjunct in xa1 is not resolvable and can be // eliminated: // xa4 & 9 // (xa2 + 2) & 9 // ((xa3 + 2) + 2) & 9 // (((6 & xa1-2) + 2) + 2) & 9 // ((6 + 2) + 2) & 9 // 6 == xa1-2 // 10 & 9 => _|_ // The remaining values resolve. xa1: (xa2 & 8) | (xa4 & 9) xa2: xa3 + 2 xa3: 6 & xa1-2 xa4: xa2 + 2 xb1: (xb2 & 8) | (xb4 & 9) xb2: xb3 + 2 xb3: (6 & (xb1 - 2)) | (xb4 & 9) xb4: xb2 + 2 // Another variant with more disjunctions. xc1 remains with two // possibilities. Technically, only the first value is valid. // However, to fully determine that, all options of the remaining // disjunction will have to be evaluated algebraically, which is // not done. xc1: xc2 & 8 | xc4 & 9 | xc5 & 9 xc2: xc3 + 2 xc3: 6 & xc1-2 xc4: xc2 + 1 xc5: xc2 + 2 // The below is resolved by setting xd1 explicitly. xd1: xd2 & 8 | xd4 & 9 | xd5 & 9 xd2: xd3 + 2 xd3: 6 & xd1-2 xd4: xd2 + 1 xd5: xd2 + 2 xd1: 8 // The below is resolved by setting xd1 explicitly to the wrong // value, resulting in an error. xe1: xe2 & 8 | xe4 & 9 | xe5 & 9 xe2: xe3 + 2 xe3: 6 & xe1-2 xe4: xe2 + 1 xe5: xe2 + 2 xe1: 9 xf1: xf2 & 8 | xf4 & 9 xf2: xf3 + 2 xf3: 6 & xf1-2 | xf4 & 9 xf4: xf2 + 2 z1: z2+1 | z3+5 // +3 for fun z2: z3 + 2 z3: z1 - 3 z3: 8 -- out/def -- // The second disjunct in xa1 is not resolvable and can be // eliminated: // xa4 & 9 // (xa2 + 2) & 9 // ((xa3 + 2) + 2) & 9 // (((6 & xa1-2) + 2) + 2) & 9 // ((6 + 2) + 2) & 9 // 6 == xa1-2 // 10 & 9 => _|_ // The remaining values resolve. xa1: 8 xa2: 8 xa4: 10 xa3: 6 // The second disjunct in xb4 can be eliminated as both disjuncts // of xb3 result in an incompatible sum when substituted. xb1: 8 xb2: 8 xb4: 10 xb3: 6 // Another variant with more disjunctions. xc1 remains with two // possibilities. Technically, only the first value is valid. // However, to fully determine that, all options of the remaining // disjunction will have to be evaluated algebraically, which is // not done. xc1: xc2 & 8 | xc4 & 9 | xc5 & 9 xc2: xc3 + 2 xc4: xc2 + 1 xc5: xc2 + 2 xc3: 6 & xc1-2 // The above is resolved by setting xd1 explicitly. xd1: 8 xd2: 8 xd4: 9 xd5: 10 xd3: 6 // The above is resolved by setting xd1 explicitly to the wrong // value, resulting in an error. xe1: _|_ // conflicting values 6 and 7 xe2: _|_ // conflicting values 6 and 7 xe4: _|_ // conflicting values 6 and 7 xe5: _|_ // conflicting values 6 and 7 xe3: _|_ // conflicting values 6 and 7 // Only one solution. xf1: 8 xf2: 8 xf4: 10 xf3: 6 z1: z2+1 | z3+5 z2: z3 + 2 z3: z1-3 & 8 -- out/legacy-debug -- <0>{xa1: 8, xa2: 8, xa4: 10, xa3: 6, xb1: 8, xb2: 8, xb4: 10, xb3: 6, xc1: ((<1>.xc2 & 8) | (<1>.xc4 & 9) | (<1>.xc5 & 9)), xc2: (<1>.xc3 + 2), xc4: (<1>.xc2 + 1), xc5: (<1>.xc2 + 2), xc3: (6 & (<1>.xc1 - 2)), xd1: 8, xd2: 8, xd4: 9, xd5: 10, xd3: 6, xe1: _|_((6 & 7):conflicting values 6 and 7), xe2: _|_((6 & 7):conflicting values 6 and 7), xe4: _|_((6 & 7):conflicting values 6 and 7), xe5: _|_((6 & 7):conflicting values 6 and 7), xe3: _|_((6 & 7):conflicting values 6 and 7), xf1: 8, xf2: 8, xf4: 10, xf3: 6, z1: ((<1>.z2 + 1) | (<1>.z3 + 5)), z2: (<1>.z3 + 2), z3: ((<1>.z1 - 3) & 8)} -- out/compile -- --- in.cue { xa1: ((〈0;xa2〉 & 8)|(〈0;xa4〉 & 9)) xa2: (〈0;xa3〉 + 2) xa3: (6 & (〈0;xa1〉 - 2)) xa4: (〈0;xa2〉 + 2) xb1: ((〈0;xb2〉 & 8)|(〈0;xb4〉 & 9)) xb2: (〈0;xb3〉 + 2) xb3: ((6 & (〈0;xb1〉 - 2))|(〈0;xb4〉 & 9)) xb4: (〈0;xb2〉 + 2) xc1: ((〈0;xc2〉 & 8)|(〈0;xc4〉 & 9)|(〈0;xc5〉 & 9)) xc2: (〈0;xc3〉 + 2) xc3: (6 & (〈0;xc1〉 - 2)) xc4: (〈0;xc2〉 + 1) xc5: (〈0;xc2〉 + 2) xd1: ((〈0;xd2〉 & 8)|(〈0;xd4〉 & 9)|(〈0;xd5〉 & 9)) xd2: (〈0;xd3〉 + 2) xd3: (6 & (〈0;xd1〉 - 2)) xd4: (〈0;xd2〉 + 1) xd5: (〈0;xd2〉 + 2) xd1: 8 xe1: ((〈0;xe2〉 & 8)|(〈0;xe4〉 & 9)|(〈0;xe5〉 & 9)) xe2: (〈0;xe3〉 + 2) xe3: (6 & (〈0;xe1〉 - 2)) xe4: (〈0;xe2〉 + 1) xe5: (〈0;xe2〉 + 2) xe1: 9 xf1: ((〈0;xf2〉 & 8)|(〈0;xf4〉 & 9)) xf2: (〈0;xf3〉 + 2) xf3: ((6 & (〈0;xf1〉 - 2))|(〈0;xf4〉 & 9)) xf4: (〈0;xf2〉 + 2) z1: ((〈0;z2〉 + 1)|(〈0;z3〉 + 5)) z2: (〈0;z3〉 + 2) z3: (〈0;z1〉 - 3) z3: 8 } -- out/eval/stats -- Leaks: 0 Freed: 52 Reused: 44 Allocs: 8 Retain: 24 Unifications: 31 Conjuncts: 128 Disjuncts: 60 -- out/evalalpha -- Errors: xe3: conflicting values 7 and 6: ./in.cue:43:6 ./in.cue:43:10 Result: (_|_){ // [eval] xa1: (int){ 8 } xa2: (int){ 8 } xa3: (int){ 6 } xa4: (int){ 10 } xb1: (int){ 8 } xb2: (int){ 11 } xb3: (int){ 6 } xb4: (int){ 13 } xc1: (int){ |((int){ 8 }, (int){ 9 }) } xc2: (int){ 8 } xc3: (_|_){ // [incomplete] xc3: unresolved disjunction 8 | 9 (type int): // ./in.cue:27:10 } xc4: (int){ 9 } xc5: (int){ 10 } xd1: (int){ 8 } xd2: (int){ 8 } xd3: (int){ 6 } xd4: (int){ 9 } xd5: (int){ 10 } xe1: (int){ 9 } xe2: (int){ 8 } xe3: (_|_){ // [eval] xe3: conflicting values 7 and 6: // ./in.cue:43:6 // ./in.cue:43:10 } xe4: (int){ 9 } xe5: (int){ 10 } xf1: (int){ 8 } xf2: (int){ 11 } xf3: (int){ 6 } xf4: (int){ 13 } z1: (int){ |((int){ 11 }, (int){ 13 }) } z2: (int){ 10 } z3: (_|_){ // [incomplete] z3: unresolved disjunction 11 | 13 (type int): // ./in.cue:55:5 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -10,22 +10,10 @@ xa2: (int){ 8 } xa3: (int){ 6 } xa4: (int){ 10 } - xb1: (_|_){ - // [incomplete] xb1: 2 errors in empty disjunction: - // xb1: unresolved disjunction 6 | 9 (type int): - // ./in.cue:16:6 - // xb2: unresolved disjunction 6 | 9 (type int): - // ./in.cue:16:6 - } - xb2: (_|_){ - // [incomplete] xb2: unresolved disjunction 6 | 9 (type int): - // ./in.cue:16:6 - } - xb3: (int){ |((int){ 6 }, (int){ 9 }) } - xb4: (_|_){ - // [incomplete] xb2: unresolved disjunction 6 | 9 (type int): - // ./in.cue:16:6 - } + xb1: (int){ 8 } + xb2: (int){ 11 } + xb3: (int){ 6 } + xb4: (int){ 13 } xc1: (int){ |((int){ 8 }, (int){ 9 }) } xc2: (int){ 8 } xc3: (_|_){ @@ -48,22 +36,10 @@ } xe4: (int){ 9 } xe5: (int){ 10 } - xf1: (_|_){ - // [incomplete] xf1: 2 errors in empty disjunction: - // xf1: unresolved disjunction 6 | 9 (type int): - // ./in.cue:49:6 - // xf2: unresolved disjunction 6 | 9 (type int): - // ./in.cue:49:6 - } - xf2: (_|_){ - // [incomplete] xf2: unresolved disjunction 6 | 9 (type int): - // ./in.cue:49:6 - } - xf3: (int){ |((int){ 6 }, (int){ 9 }) } - xf4: (_|_){ - // [incomplete] xf2: unresolved disjunction 6 | 9 (type int): - // ./in.cue:49:6 - } + xf1: (int){ 8 } + xf2: (int){ 11 } + xf3: (int){ 6 } + xf4: (int){ 13 } z1: (int){ |((int){ 11 }, (int){ 13 }) } z2: (int){ 10 } z3: (_|_){ -- diff/todo/p1 -- x(b|f)(2|4): resolve incorrectly. This is related to completeNodeTasks. -- diff/explanation -- x(e|f)*: is better to have an error at each field. z3: include the "unchecked" validator. In general, new evaluator seems better. -- out/eval -- Errors: xe3: conflicting values 7 and 6: ./in.cue:43:6 ./in.cue:43:10 Result: (_|_){ // [eval] xa1: (int){ 8 } xa2: (int){ 8 } xa3: (int){ 6 } xa4: (int){ 10 } xb1: (_|_){ // [incomplete] xb1: 2 errors in empty disjunction: // xb1: unresolved disjunction 6 | 9 (type int): // ./in.cue:16:6 // xb2: unresolved disjunction 6 | 9 (type int): // ./in.cue:16:6 } xb2: (_|_){ // [incomplete] xb2: unresolved disjunction 6 | 9 (type int): // ./in.cue:16:6 } xb3: (int){ |((int){ 6 }, (int){ 9 }) } xb4: (_|_){ // [incomplete] xb2: unresolved disjunction 6 | 9 (type int): // ./in.cue:16:6 } xc1: (int){ |((int){ 8 }, (int){ 9 }) } xc2: (int){ 8 } xc3: (_|_){ // [incomplete] xc3: unresolved disjunction 8 | 9 (type int): // ./in.cue:27:10 } xc4: (int){ 9 } xc5: (int){ 10 } xd1: (int){ 8 } xd2: (int){ 8 } xd3: (int){ 6 } xd4: (int){ 9 } xd5: (int){ 10 } xe1: (int){ 9 } xe2: (int){ 8 } xe3: (_|_){ // [eval] xe3: conflicting values 7 and 6: // ./in.cue:43:6 // ./in.cue:43:10 } xe4: (int){ 9 } xe5: (int){ 10 } xf1: (_|_){ // [incomplete] xf1: 2 errors in empty disjunction: // xf1: unresolved disjunction 6 | 9 (type int): // ./in.cue:49:6 // xf2: unresolved disjunction 6 | 9 (type int): // ./in.cue:49:6 } xf2: (_|_){ // [incomplete] xf2: unresolved disjunction 6 | 9 (type int): // ./in.cue:49:6 } xf3: (int){ |((int){ 6 }, (int){ 9 }) } xf4: (_|_){ // [incomplete] xf2: unresolved disjunction 6 | 9 (type int): // ./in.cue:49:6 } z1: (int){ |((int){ 11 }, (int){ 13 }) } z2: (int){ 10 } z3: (_|_){ // [incomplete] z3: unresolved disjunction 11 | 13 (type int): // ./in.cue:55:5 } } 052_resolved_self-reference_cycles_with_disjunction_with_defaults.txtar000066400000000000000000000133541474664451600363050ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/cycle#name: resolved self-reference cycles with disjunction with defaults #evalPartial -- in.cue -- // The disjunction in xa could be resolved, but as disjunctions // are not resolved for expression, it remains unresolved. xa1: (xa2 & 8) | *(xa4 & 9) xa2: xa3 + 2 xa3: 6 & xa1-2 xa4: xa2 + 2 xb1: *(xb2 & 8) | (xb4 & 9) xb2: xb3 + 2 xb3: *(6 & (xb1 - 2)) | (xb4 & 9) xb4: xb2 + 2 // Another variant with more disjunctions. xc1 remains with two // possibilities. Technically, only the first value is valid. // However, to fully determine that, all options of the remaining // disjunction will have to be evaluated algebraically, which is // not done. xc1: *(xc2 & 8) | (xc4 & 9) | (xc5 & 9) xc2: xc3 + 2 xc3: 6 & xc1-2 xc4: xc2 + 1 xc5: xc2 + 2 // The above is resolved by setting xd1 explicitly. xd1: *(xd2 & 8) | xd4 & 9 | xd5 & 9 xd2: xd3 + 2 xd3: 6 & xd1-2 xd4: xd2 + 1 xd5: xd2 + 2 // The above is resolved by setting xd1 explicitly to the wrong // value, resulting in an error. xe1: *(xe2 & 8) | xe4 & 9 | xe5 & 9 xe2: xe3 + 2 xe3: 6 & xe1-2 xe4: xe2 + 1 xe5: xe2 + 2 xe1: 9 z1: *(z2 + 1) | z3+5 z2: z3 + 2 z3: z1 - 3 z3: 8 -- out/def -- // The disjunction in xa could be resolved, but as disjunctions // are not resolved for expression, it remains unresolved. xa1: 8 xa2: 8 xa4: 10 xa3: 6 // As xb3 is a disjunction, xb2 cannot be resolved and evaluating // the cycle completely is broken. However, it is not an error // as the user might still resolve the disjunction. xb1: 8 xb2: 8 xb4: 10 xb3: 6 // Another variant with more disjunctions. xc1 remains with two // possibilities. Technically, only the first value is valid. // However, to fully determine that, all options of the remaining // disjunction will have to be evaluated algebraically, which is // not done. xc1: *8 | 9 | _|_ // conflicting values 10 and 9 xc2: 8 xc4: 9 xc5: 10 xc3: 6 // The above is resolved by setting xd1 explicitly. xd1: *8 | 9 | _|_ // conflicting values 10 and 9 xd2: 8 xd4: 9 xd5: 10 xd3: 6 // The above is resolved by setting xd1 explicitly to the wrong // value, resulting in an error. xe1: _|_ // conflicting values 6 and 7 xe2: _|_ // conflicting values 6 and 7 xe4: _|_ // conflicting values 6 and 7 xe5: _|_ // conflicting values 6 and 7 xe3: _|_ // conflicting values 6 and 7 z1: *11 | 13 z2: 10 z3: 8 -- out/legacy-debug -- <0>{xa1: 8, xa2: 8, xa4: 10, xa3: 6, xb1: 8, xb2: 8, xb4: 10, xb3: 6, xc1: (*8 | 9), xc2: 8, xc4: 9, xc5: 10, xc3: 6, xd1: (*8 | 9), xd2: 8, xd4: 9, xd5: 10, xd3: 6, xe1: _|_((6 & 7):conflicting values 6 and 7), xe2: _|_((6 & 7):conflicting values 6 and 7), xe4: _|_((6 & 7):conflicting values 6 and 7), xe5: _|_((6 & 7):conflicting values 6 and 7), xe3: _|_((6 & 7):conflicting values 6 and 7), z1: (*11 | 13), z2: 10, z3: 8} -- out/compile -- --- in.cue { xa1: ((〈0;xa2〉 & 8)|*(〈0;xa4〉 & 9)) xa2: (〈0;xa3〉 + 2) xa3: (6 & (〈0;xa1〉 - 2)) xa4: (〈0;xa2〉 + 2) xb1: (*(〈0;xb2〉 & 8)|(〈0;xb4〉 & 9)) xb2: (〈0;xb3〉 + 2) xb3: (*(6 & (〈0;xb1〉 - 2))|(〈0;xb4〉 & 9)) xb4: (〈0;xb2〉 + 2) xc1: (*(〈0;xc2〉 & 8)|(〈0;xc4〉 & 9)|(〈0;xc5〉 & 9)) xc2: (〈0;xc3〉 + 2) xc3: (6 & (〈0;xc1〉 - 2)) xc4: (〈0;xc2〉 + 1) xc5: (〈0;xc2〉 + 2) xd1: (*(〈0;xd2〉 & 8)|(〈0;xd4〉 & 9)|(〈0;xd5〉 & 9)) xd2: (〈0;xd3〉 + 2) xd3: (6 & (〈0;xd1〉 - 2)) xd4: (〈0;xd2〉 + 1) xd5: (〈0;xd2〉 + 2) xe1: (*(〈0;xe2〉 & 8)|(〈0;xe4〉 & 9)|(〈0;xe5〉 & 9)) xe2: (〈0;xe3〉 + 2) xe3: (6 & (〈0;xe1〉 - 2)) xe4: (〈0;xe2〉 + 1) xe5: (〈0;xe2〉 + 2) xe1: 9 z1: (*(〈0;z2〉 + 1)|(〈0;z3〉 + 5)) z2: (〈0;z3〉 + 2) z3: (〈0;z1〉 - 3) z3: 8 } -- out/eval/stats -- Leaks: 0 Freed: 44 Reused: 36 Allocs: 8 Retain: 25 Unifications: 27 Conjuncts: 82 Disjuncts: 58 -- out/evalalpha -- Errors: xe3: conflicting values 7 and 6: ./in.cue:35:6 ./in.cue:35:10 Result: (_|_){ // [eval] xa1: (int){ 8 } xa2: (int){ 8 } xa3: (int){ 6 } xa4: (int){ 10 } xb1: (int){ 8 } xb2: (int){ 11 } xb3: (int){ 6 } xb4: (int){ 13 } xc1: (int){ |(*(int){ 8 }, (int){ 9 }) } xc2: (int){ 8 } xc3: (int){ 6 } xc4: (int){ 9 } xc5: (int){ 10 } xd1: (int){ |(*(int){ 8 }, (int){ 9 }) } xd2: (int){ 8 } xd3: (int){ 6 } xd4: (int){ 9 } xd5: (int){ 10 } xe1: (int){ 9 } xe2: (int){ 8 } xe3: (_|_){ // [eval] xe3: conflicting values 7 and 6: // ./in.cue:35:6 // ./in.cue:35:10 } xe4: (int){ 9 } xe5: (int){ 10 } z1: (int){ |(*(int){ 11 }, (int){ 13 }) } z2: (int){ 10 } z3: (int){ 8 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -11,9 +11,9 @@ xa3: (int){ 6 } xa4: (int){ 10 } xb1: (int){ 8 } - xb2: (int){ 8 } - xb3: (int){ |(*(int){ 6 }, (int){ 9 }) } - xb4: (int){ 10 } + xb2: (int){ 11 } + xb3: (int){ 6 } + xb4: (int){ 13 } xc1: (int){ |(*(int){ 8 }, (int){ 9 }) } xc2: (int){ 8 } xc3: (int){ 6 } -- diff/todo/p1 -- Verify differences. xb2: Incorrect result. xb4: Incorrect result. This is related to completeNodeTasks. -- out/eval -- Errors: xe3: conflicting values 7 and 6: ./in.cue:35:6 ./in.cue:35:10 Result: (_|_){ // [eval] xa1: (int){ 8 } xa2: (int){ 8 } xa3: (int){ 6 } xa4: (int){ 10 } xb1: (int){ 8 } xb2: (int){ 8 } xb3: (int){ |(*(int){ 6 }, (int){ 9 }) } xb4: (int){ 10 } xc1: (int){ |(*(int){ 8 }, (int){ 9 }) } xc2: (int){ 8 } xc3: (int){ 6 } xc4: (int){ 9 } xc5: (int){ 10 } xd1: (int){ |(*(int){ 8 }, (int){ 9 }) } xd2: (int){ 8 } xd3: (int){ 6 } xd4: (int){ 9 } xd5: (int){ 10 } xe1: (int){ 9 } xe2: (int){ 8 } xe3: (_|_){ // [eval] xe3: conflicting values 7 and 6: // ./in.cue:35:6 // ./in.cue:35:10 } xe4: (int){ 9 } xe5: (int){ 10 } z1: (int){ |(*(int){ 11 }, (int){ 13 }) } z2: (int){ 10 } z3: (int){ 8 } } cue-lang-cue-db9cc73/cue/testdata/cycle/builtins.txtar000066400000000000000000000440161474664451600231060ustar00rootroot00000000000000-- in.cue -- import "regexp" // Issue #655 // When evaluating a value into a struct, and then back into a value, the // evaluation mode flips from Partial to AllConjunctsDone to Back. This is // typically not an issue, but if a referred field is within a struct generated // by a builtin, effectively the entire struct needs to be evaluated and special // care should be taking to not evaluate too early. builtinCyclePerm0: { X: "mod.test" Y: { #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) host: #components.host } X: Y.host } builtinCyclePerm1: { X: Y.host Y: { #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) host: #components.host } X: "mod.test" } builtinCyclePerm2: { Y: { #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) host: #components.host } X: Y.host X: "mod.test" } builtinCyclePerm3: { Y: { #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) host: #components.host } X: "mod.test" X: Y.host } builtinCyclePerm4: { X: "mod.test" X: Y.host Y: { #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) host: #components.host } } builtinCyclePerm5: { X: Y.host X: "mod.test" Y: { #components: regexp.FindNamedSubmatch(#"^(?P[[:alnum:].]+)$"#, X) host: #components.host } } -- matchn.cue -- // This should not be a structural cycle, as the list type is "optional". issue3410: { _s _s: { #x: matchN(1, [_s, [..._s]]) } } issue3420: { matches1: { #S: matchN(1, [_, _|_]) s: 2 } } issue3443: { matchIf: { #S: matchIf({x?: "b"}, {n?: #S & (int | {})}, _) } noCycle: { // This is not a structural cycle, and should not hang, as n? is optional. #S: matchN(1, [{n?: #S & (int | {})}]) noHang: { s: #S s: n: n: _ } } noCycle2: { #S: matchN(1, [{n?: (int | #S)}]) } cycle1: { // This correct CUE, as matchN allows for schema to be errors. We should // probably have a vet rule to catch this,though. #S: matchN(1, [{n: #S}]) // This is not an error as the result is structure shared. Not sure if // this should be accepted. ok: { s: #S s: _ } // This unifies deep enough to cause a structural cycle. It probably // should not. cycle: { s: #S s: n: n: _ } } cycle2: { // TODO: this should probably fail, or at least be consistent with // cycle1.cycle. fail: #S: matchN(1, [{n: #S}]) & {n: n: n: _} } } issue3633: final: { // With nested matchNs as below, the schema will become an incomplete error // as a value of the root vertex. Make sure this edge case is properly // handled. data: {} & #s #s: matchN(1, [matchN(1, [{a!: _}])]) } -- todo/p1 -- issue3443.noCycle: fix hang -- out/evalalpha/stats -- Leaks: 227 Freed: 17 Reused: 17 Allocs: 227 Retain: 0 Unifications: 191 Conjuncts: 742 Disjuncts: 28 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 14 -Freed: 249 -Reused: 234 -Allocs: 29 -Retain: 70 +Leaks: 227 +Freed: 17 +Reused: 17 +Allocs: 227 +Retain: 0 -Unifications: 227 -Conjuncts: 431 -Disjuncts: 309 +Unifications: 191 +Conjuncts: 742 +Disjuncts: 28 -- out/eval/stats -- Leaks: 14 Freed: 249 Reused: 234 Allocs: 29 Retain: 70 Unifications: 227 Conjuncts: 431 Disjuncts: 309 -- out/evalalpha -- Errors: issue3443.matchIf.#S: cannot call non-function matchIf (type struct): ./matchn.cue:16:7 issue3443.cycle1.cycle.s: invalid value {n:{n:_}} (does not satisfy matchN): 0 matched, expected 1: ./matchn.cue:35:7 ./matchn.cue:35:14 ./matchn.cue:47:7 ./matchn.cue:48:7 issue3443.cycle2.fail.#S: invalid value {n:{n:{n:_}}} (does not satisfy matchN): 0 matched, expected 1: ./matchn.cue:55:13 ./matchn.cue:55:20 Result: (_|_){ // [eval] builtinCyclePerm0: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } builtinCyclePerm1: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } builtinCyclePerm2: (struct){ Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } X: (string){ "mod.test" } } builtinCyclePerm3: (struct){ Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } X: (string){ "mod.test" } } builtinCyclePerm4: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } builtinCyclePerm5: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } issue3410: (struct){ _s: (struct){ #x: (_){ matchN(1, (#list){ 0: (_|_){// &[〈2;_s〉] } 1: (_|_){// &[[ // ...〈3;_s〉, // ]] } }) } } #x: (_){ matchN(1, (#list){ 0: (_|_){// &[〈2;_s〉] } 1: (_|_){// &[[ // ...〈3;_s〉, // ]] } }) } } issue3420: (struct){ matches1: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// &[_] } 1: (_|_){// &[_|_(explicit error (_|_ literal) in source)] } }) } s: (int){ 2 } } } issue3443: (_|_){ // [eval] matchIf: (_|_){ // [eval] #S: (_|_){ // [eval] issue3443.matchIf.#S: cannot call non-function matchIf (type struct): // ./matchn.cue:16:7 } } noCycle: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // n?: (〈2;#S〉 & (int|{})) // }] } }) } noHang: (struct){ s: (#struct){ n: (struct){ n: (_){ _ } } } } } noCycle2: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // n?: (int|〈2;#S〉) // }] } }) } } cycle1: (_|_){ // [eval] #S: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // n: 〈2;#S〉 // }] } }) } ok: (struct){ s: (_){ matchN(1, (#list){ 0: (_|_){// &[{ // n: 〈2;#S〉 // }] } }) } } cycle: (_|_){ // [eval] s: (_|_){ // [eval] issue3443.cycle1.cycle.s: invalid value {n:{n:_}} (does not satisfy matchN): 0 matched, expected 1: // ./matchn.cue:35:7 // ./matchn.cue:35:14 // ./matchn.cue:47:7 // ./matchn.cue:48:7 n: (struct){ n: (_){ _ } } } } } cycle2: (_|_){ // [eval] fail: (_|_){ // [eval] #S: (_|_){ // [eval] issue3443.cycle2.fail.#S: invalid value {n:{n:{n:_}}} (does not satisfy matchN): 0 matched, expected 1: // ./matchn.cue:55:13 // ./matchn.cue:55:20 n: (#struct){ n: (#struct){ n: (_){ _ } } } } } } } issue3633: (struct){ final: (struct){ data: (_|_){ // [incomplete] issue3633.final.data: invalid value {} (does not satisfy matchN): 0 matched, expected 1: // ./matchn.cue:63:6 // ./matchn.cue:62:8 // ./matchn.cue:63:13 } #s: (_){ matchN(1, (#list){ 0: (_|_){// &[matchN(1, [ // { // a!: _ // }, // ])] } }) } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,6 +1,11 @@ Errors: issue3443.matchIf.#S: cannot call non-function matchIf (type struct): ./matchn.cue:16:7 +issue3443.cycle1.cycle.s: invalid value {n:{n:_}} (does not satisfy matchN): 0 matched, expected 1: + ./matchn.cue:35:7 + ./matchn.cue:35:14 + ./matchn.cue:47:7 + ./matchn.cue:48:7 issue3443.cycle2.fail.#S: invalid value {n:{n:{n:_}}} (does not satisfy matchN): 0 matched, expected 1: ./matchn.cue:55:13 ./matchn.cue:55:20 @@ -65,20 +70,20 @@ issue3410: (struct){ _s: (struct){ #x: (_){ matchN(1, (#list){ - 0: (_|_){// 〈2;_s〉 - } - 1: (_|_){// [ + 0: (_|_){// &[〈2;_s〉] + } + 1: (_|_){// &[[ // ...〈3;_s〉, - // ] + // ]] } }) } } #x: (_){ matchN(1, (#list){ - 0: (_|_){// 〈2;_s〉 - } - 1: (_|_){// [ + 0: (_|_){// &[〈2;_s〉] + } + 1: (_|_){// &[[ // ...〈3;_s〉, - // ] + // ]] } }) } } @@ -85,9 +90,9 @@ issue3420: (struct){ matches1: (struct){ #S: (_){ matchN(1, (#list){ - 0: (_|_){// _ - } - 1: (_|_){// _|_(explicit error (_|_ literal) in source) + 0: (_|_){// &[_] + } + 1: (_|_){// &[_|_(explicit error (_|_ literal) in source)] } }) } s: (int){ 2 } @@ -104,13 +109,13 @@ } noCycle: (struct){ #S: (_){ matchN(1, (#list){ - 0: (_|_){// { + 0: (_|_){// &[{ // n?: (〈2;#S〉 & (int|{})) - // } + // }] } }) } noHang: (struct){ - s: (struct){ + s: (#struct){ n: (struct){ n: (_){ _ } } @@ -119,29 +124,36 @@ } noCycle2: (struct){ #S: (_){ matchN(1, (#list){ - 0: (_|_){// { + 0: (_|_){// &[{ // n?: (int|〈2;#S〉) - // } - } - }) } - } - cycle1: (struct){ - #S: (_){ matchN(1, (#list){ - 0: (_|_){// { + // }] + } + }) } + } + cycle1: (_|_){ + // [eval] + #S: (_){ matchN(1, (#list){ + 0: (_|_){// &[{ // n: 〈2;#S〉 - // } + // }] } }) } ok: (struct){ s: (_){ matchN(1, (#list){ - 0: (_|_){// { + 0: (_|_){// &[{ // n: 〈2;#S〉 - // } + // }] } }) } } - cycle: (struct){ - s: (struct){ + cycle: (_|_){ + // [eval] + s: (_|_){ + // [eval] issue3443.cycle1.cycle.s: invalid value {n:{n:_}} (does not satisfy matchN): 0 matched, expected 1: + // ./matchn.cue:35:7 + // ./matchn.cue:35:14 + // ./matchn.cue:47:7 + // ./matchn.cue:48:7 n: (struct){ n: (_){ _ } } @@ -174,11 +186,11 @@ // ./matchn.cue:63:13 } #s: (_){ matchN(1, (#list){ - 0: (_|_){// matchN(1, [ + 0: (_|_){// &[matchN(1, [ // { // a!: _ // }, - // ]) + // ])] } }) } } -- diff/todo/p2 -- issue3443: Sort out differences in reporting of cycles. -- out/eval -- Errors: issue3443.matchIf.#S: cannot call non-function matchIf (type struct): ./matchn.cue:16:7 issue3443.cycle2.fail.#S: invalid value {n:{n:{n:_}}} (does not satisfy matchN): 0 matched, expected 1: ./matchn.cue:55:13 ./matchn.cue:55:20 Result: (_|_){ // [eval] builtinCyclePerm0: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } builtinCyclePerm1: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } builtinCyclePerm2: (struct){ Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } X: (string){ "mod.test" } } builtinCyclePerm3: (struct){ Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } X: (string){ "mod.test" } } builtinCyclePerm4: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } builtinCyclePerm5: (struct){ X: (string){ "mod.test" } Y: (struct){ #components: (#struct){ host: (string){ "mod.test" } } host: (string){ "mod.test" } } } issue3410: (struct){ _s: (struct){ #x: (_){ matchN(1, (#list){ 0: (_|_){// 〈2;_s〉 } 1: (_|_){// [ // ...〈3;_s〉, // ] } }) } } #x: (_){ matchN(1, (#list){ 0: (_|_){// 〈2;_s〉 } 1: (_|_){// [ // ...〈3;_s〉, // ] } }) } } issue3420: (struct){ matches1: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// _ } 1: (_|_){// _|_(explicit error (_|_ literal) in source) } }) } s: (int){ 2 } } } issue3443: (_|_){ // [eval] matchIf: (_|_){ // [eval] #S: (_|_){ // [eval] issue3443.matchIf.#S: cannot call non-function matchIf (type struct): // ./matchn.cue:16:7 } } noCycle: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// { // n?: (〈2;#S〉 & (int|{})) // } } }) } noHang: (struct){ s: (struct){ n: (struct){ n: (_){ _ } } } } } noCycle2: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// { // n?: (int|〈2;#S〉) // } } }) } } cycle1: (struct){ #S: (_){ matchN(1, (#list){ 0: (_|_){// { // n: 〈2;#S〉 // } } }) } ok: (struct){ s: (_){ matchN(1, (#list){ 0: (_|_){// { // n: 〈2;#S〉 // } } }) } } cycle: (struct){ s: (struct){ n: (struct){ n: (_){ _ } } } } } cycle2: (_|_){ // [eval] fail: (_|_){ // [eval] #S: (_|_){ // [eval] issue3443.cycle2.fail.#S: invalid value {n:{n:{n:_}}} (does not satisfy matchN): 0 matched, expected 1: // ./matchn.cue:55:13 // ./matchn.cue:55:20 n: (#struct){ n: (#struct){ n: (_){ _ } } } } } } } issue3633: (struct){ final: (struct){ data: (_|_){ // [incomplete] issue3633.final.data: invalid value {} (does not satisfy matchN): 0 matched, expected 1: // ./matchn.cue:63:6 // ./matchn.cue:62:8 // ./matchn.cue:63:13 } #s: (_){ matchN(1, (#list){ 0: (_|_){// matchN(1, [ // { // a!: _ // }, // ]) } }) } } } } -- out/compile -- --- in.cue { builtinCyclePerm0: { X: "mod.test" Y: { #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) host: 〈0;#components〉.host } X: 〈0;Y〉.host } builtinCyclePerm1: { X: 〈0;Y〉.host Y: { #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) host: 〈0;#components〉.host } X: "mod.test" } builtinCyclePerm2: { Y: { #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) host: 〈0;#components〉.host } X: 〈0;Y〉.host X: "mod.test" } builtinCyclePerm3: { Y: { #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) host: 〈0;#components〉.host } X: "mod.test" X: 〈0;Y〉.host } builtinCyclePerm4: { X: "mod.test" X: 〈0;Y〉.host Y: { #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) host: 〈0;#components〉.host } } builtinCyclePerm5: { X: 〈0;Y〉.host X: "mod.test" Y: { #components: 〈import;regexp〉.FindNamedSubmatch("^(?P[[:alnum:].]+)$", 〈1;X〉) host: 〈0;#components〉.host } } } --- matchn.cue { issue3410: { 〈0;_s〉 _s: { #x: matchN(1, [ 〈2;_s〉, [ ...〈3;_s〉, ], ]) } } issue3420: { matches1: { #S: matchN(1, [ _, _|_(explicit error (_|_ literal) in source), ]) s: 2 } } issue3443: { matchIf: { #S: 〈1;matchIf〉({ x?: "b" }, { n?: (〈1;#S〉 & (int|{})) }, _) } noCycle: { #S: matchN(1, [ { n?: (〈2;#S〉 & (int|{})) }, ]) noHang: { s: 〈1;#S〉 s: { n: { n: _ } } } } noCycle2: { #S: matchN(1, [ { n?: (int|〈2;#S〉) }, ]) } cycle1: { #S: matchN(1, [ { n: 〈2;#S〉 }, ]) ok: { s: 〈1;#S〉 s: _ } cycle: { s: 〈1;#S〉 s: { n: { n: _ } } } } cycle2: { fail: { #S: (matchN(1, [ { n: 〈2;#S〉 }, ]) & { n: { n: { n: _ } } }) } } } issue3633: { final: { data: ({} & 〈0;#s〉) #s: matchN(1, [ matchN(1, [ { a!: _ }, ]), ]) } } } cue-lang-cue-db9cc73/cue/testdata/cycle/chain.txtar000066400000000000000000002132231474664451600223350ustar00rootroot00000000000000-- in.cue -- import "list" // The following just chains existing fields and should NOT trigger a cycle // detection error. chain: t1: { #maxiter: 2 // Trigger lookup of a.x0 before the "regular" evaluation of a. x: a.x0 a: { for k, _ in [0, 1] { "x\(k)": (#DepthF & {#in: a["x\(k+1)"]}).#out } } a: x2: null #DepthF: { #in: _ #out: {} } } chain: t2: p1: { X: 1 // Reference X through x.x0 before X is inserted. for v in list.Concat([[0, X], []]) { x: "x\(v)": {} } x: _ x.x0 } chain: t2: p2: { // Reference X through x.x0 before X is inserted. for v in list.Concat([[0, X], []]) { x: "x\(v)": {} } x: _ x.x0 X: 1 } chain: t3: p1: { X: 1 for v in list.Range(0, X, 1) { x: "x\(v)": {} } x: _ x.x0 } chain: t3: p1: { for v in list.Range(0, X, 1) { x: "x\(v)": {} } x: _ x.x0 X: 1 } -- issue2052.cue -- import ( "list" "math" ) issue2052: reduced: t1: { A: a: _ Depth: { #maxiter: 1 if math.Abs(#maxiter) == 1 { funcs: "\(0)": A } funcs: {} funcs["0"] } } issue2052: reduced: t2: { A: a: _ Depth: { maxiter: 1 for k, v in list.Range(0, maxiter, 1) { funcs: "\(0)": A } funcs: {} funcs["0"] } } issue2052: medium: t1: { #Depth: { #maxiter: 4 for k, v in list.Range(0, #maxiter, 1) { #funcs: "\(k)": (#DepthF & {#next: #funcs["\(k+1)"]}).#func } #funcs: "\(#maxiter)": null #funcs["0"] } #DepthF: { #next: _ #func: { #in: _ #basic: string | null out: { if (#in & #basic) != _|_ {1} if (#in & #basic) == _|_ { list.Max([for k, v in #in {(#next & {#in: v}).out}]) + 1 } } } } tree: "bar" d: #Depth & {#in: tree} } issue2052: medium: t2: { #Depth: { #maxiter: 4 for k, v in list.Range(0, #maxiter, 1) { #funcs: "\(k)": (#DepthF & {#next: #funcs["\(k+1)"]}).#func } #funcs:{ for k, v in list.Range(0, #maxiter, 1) { "\(k)": (#DepthF & {#next: #funcs["\(k+1)"]}).#func } } #funcs: "\(#maxiter)": null #funcs["0"] } #DepthF: { #next: _ #func: { #in: _ #basic: string | null out: { if (#in & #basic) != _|_ {1} if (#in & #basic) == _|_ { list.Max([for k, v in #in {(#next & {#in: v}).out}]) + 1 } } } } tree: "bar" d: #Depth & {#in: tree} } issue2052: full: { #RecurseN: { // this is the bound on our recursion #maxiter: uint | *4 // This is the function list element // we generate this to simulate recursion #funcFactory: { #next: _ #func: _ } // this is our "recursion unrolling" for k, v in list.Range(0, #maxiter, 1) { // this is where we build up our indexed functions and the references between them #funcs: "\(k)": (#funcFactory & {#next: #funcs["\(k+1)"]}).#func } // our final value needs to be null #funcs: "\(#maxiter)": null // we embed the head of the list so that the values // we write this into can be used like other CUE "functions" #funcs["0"] } #DepthF: { #next: _ #func: { #in: _ #basic: int | number | string | bytes | null out: { // if we have a basic type, we are at a leaf, depth is 1 if (#in & #basic) != _|_ {1} // if we are not a basic type, then we are 1 + the max of children if (#in & #basic) == _|_ { // this is our "recursion" for each child let depths = [for k, v in #in {(#next & {#in: v}).out}] list.Max(depths) + 1 } } } } #Depth: #RecurseN & {#maxiter: 11, #funcFactory: #DepthF} tree: { a: { foo: "bar" a: b: c: "d" } cow: "moo" } d: #Depth & {#in: tree} } -- out/evalalpha/stats -- Leaks: 12801 Freed: 1484 Reused: 1483 Allocs: 12802 Retain: 0 Unifications: 5066 Conjuncts: 67167 Disjuncts: 8919 -- out/evalalpha -- (struct){ chain: (struct){ t1: (struct){ #maxiter: (int){ 2 } x: (#struct){ } a: (struct){ x2: (null){ null } x0: (#struct){ } x1: (#struct){ } } #DepthF: (#struct){ #in: (_){ _ } #out: (#struct){ } } } t2: (struct){ p1: (struct){ X: (int){ 1 } x: (struct){ x0: (struct){ } x1: (struct){ } } } p2: (struct){ x: (struct){ x0: (struct){ } x1: (struct){ } } X: (int){ 1 } } } t3: (struct){ p1: (struct){ X: (int){ 1 } x: (struct){ x0: (struct){ } } } } } issue2052: (struct){ reduced: (struct){ t1: (struct){ A: (struct){ a: (_){ _ } } Depth: (struct){ #maxiter: (int){ 1 } funcs: (struct){ "0": ~(issue2052.reduced.t1.A) } a: (_){ _ } } } t2: (struct){ A: (struct){ a: (_){ _ } } Depth: (struct){ maxiter: (int){ 1 } funcs: (struct){ "0": ~(issue2052.reduced.t2.A) } a: (_){ _ } } } } medium: (struct){ t1: (struct){ #Depth: (#struct){ #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } #DepthF: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } tree: (string){ "bar" } d: (#struct){ #in: (string){ "bar" } #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } t2: (struct){ #Depth: (#struct){ #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } #DepthF: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } tree: (string){ "bar" } d: (#struct){ #in: (string){ "bar" } #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } } full: (struct){ #RecurseN: (_|_){ // [incomplete] issue2052.full.#RecurseN: error in call to list.Range: non-concrete value _: // ./issue2052.cue:111:15 #maxiter: (int){ |(*(int){ 4 }, (int){ &(>=0, int) }) } #funcFactory: (#struct){ #next: (_){ _ } #func: (_){ _ } } #funcs: (_|_){ // [incomplete] issue2052.full.#RecurseN: error in call to list.Range: non-concrete value _: // ./issue2052.cue:111:15 // issue2052.full.#RecurseN.#funcs: invalid interpolation: non-concrete value _ (type _): // ./issue2052.cue:117:11 } } #DepthF: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } } #Depth: (#struct){ #maxiter: (int){ 11 } #funcFactory: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } } #funcs: (#struct){ "11": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "4": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "5": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "6": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "7": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "8": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "9": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "10": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } } #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } tree: (struct){ a: (struct){ foo: (string){ "bar" } a: (struct){ b: (struct){ c: (string){ "d" } } } } cow: (string){ "moo" } } d: (#struct){ #in: (#struct){ a: (#struct){ foo: (string){ "bar" } a: (#struct){ b: (#struct){ c: (string){ "d" } } } } cow: (string){ "moo" } } #maxiter: (int){ 11 } #funcFactory: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } } #funcs: (#struct){ "11": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "4": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "5": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "6": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "7": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "8": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "9": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } "10": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 5 let depths#1multi = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] } } } } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 56 -Freed: 1830 -Reused: 1816 -Allocs: 70 -Retain: 169 +Leaks: 12801 +Freed: 1484 +Reused: 1483 +Allocs: 12802 +Retain: 0 -Unifications: 801 -Conjuncts: 3177 -Disjuncts: 1979 +Unifications: 5066 +Conjuncts: 67167 +Disjuncts: 8919 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -27,15 +27,11 @@ } } } - p2: (_|_){ - // [incomplete] chain.t2.p2.0.1: invalid interpolation: cycle error referencing X: - // ./in.cue:44:6 - // ./in.cue:43:28 - x: (_|_){ - // [incomplete] chain.t2.p2.0.1: invalid interpolation: cycle error referencing X: - // ./in.cue:44:6 - // ./in.cue:43:28 - x0: (struct){ + p2: (struct){ + x: (struct){ + x0: (struct){ + } + x1: (struct){ } } X: (int){ 1 } @@ -60,9 +56,7 @@ Depth: (struct){ #maxiter: (int){ 1 } funcs: (struct){ - "0": (struct){ - a: (_){ _ } - } + "0": ~(issue2052.reduced.t1.A) } a: (_){ _ } } @@ -74,9 +68,7 @@ Depth: (struct){ maxiter: (int){ 1 } funcs: (struct){ - "0": (struct){ - a: (_){ _ } - } + "0": ~(issue2052.reduced.t2.A) } a: (_){ _ } } @@ -123,100 +115,100 @@ } tree: (string){ "bar" } d: (#struct){ - #maxiter: (int){ 4 } - #funcs: (#struct){ - "4": (null){ null } - "0": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "1": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "2": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "3": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - } - #in: (string){ "bar" } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - } - t2: (struct){ - #Depth: (#struct){ - #maxiter: (int){ 4 } - #funcs: (#struct){ - "4": (null){ null } - "0": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "1": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "2": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "3": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - } - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - #DepthF: (#struct){ - #next: (_){ _ } - #func: (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - } - tree: (string){ "bar" } - d: (#struct){ - #maxiter: (int){ 4 } - #funcs: (#struct){ - "4": (null){ null } - "0": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "1": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "2": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - "3": (#struct){ - #in: (_){ _ } - #basic: ((null|string)){ |((string){ string }, (null){ null }) } - out: (int){ 1 } - } - } - #in: (string){ "bar" } + #in: (string){ "bar" } + #maxiter: (int){ 4 } + #funcs: (#struct){ + "4": (null){ null } + "0": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "1": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "2": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "3": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + } + t2: (struct){ + #Depth: (#struct){ + #maxiter: (int){ 4 } + #funcs: (#struct){ + "4": (null){ null } + "0": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "1": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "2": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "3": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + } + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + #DepthF: (#struct){ + #next: (_){ _ } + #func: (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + } + tree: (string){ "bar" } + d: (#struct){ + #in: (string){ "bar" } + #maxiter: (int){ 4 } + #funcs: (#struct){ + "4": (null){ null } + "0": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "1": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "2": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + "3": (#struct){ + #in: (_){ _ } + #basic: ((null|string)){ |((string){ string }, (null){ null }) } + out: (int){ 1 } + } + } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } @@ -223,19 +215,19 @@ } } full: (struct){ - #RecurseN: (_){ - _ + #RecurseN: (_|_){ + // [incomplete] issue2052.full.#RecurseN: error in call to list.Range: non-concrete value _: + // ./issue2052.cue:111:15 #maxiter: (int){ |(*(int){ 4 }, (int){ &(>=0, int) }) } #funcFactory: (#struct){ #next: (_){ _ } #func: (_){ _ } } - #funcs: (#struct){ - "4": (null){ null } - "0": (_){ _ } - "1": (_){ _ } - "2": (_){ _ } - "3": (_){ _ } + #funcs: (_|_){ + // [incomplete] issue2052.full.#RecurseN: error in call to list.Range: non-concrete value _: + // ./issue2052.cue:111:15 + // issue2052.full.#RecurseN.#funcs: invalid interpolation: non-concrete value _ (type _): + // ./issue2052.cue:117:11 } } #DepthF: (#struct){ @@ -245,7 +237,13 @@ #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 - let depths#1 = (_){ _ } + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] } } } @@ -258,98 +256,170 @@ #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 - let depths#1 = (_){ _ } - } - } - } - #funcs: (#struct){ - "11": (null){ null } - "0": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "1": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "2": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "3": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "4": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "5": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "6": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "7": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "8": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "9": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "10": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + } + #funcs: (#struct){ + "11": (null){ null } + "0": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "1": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "2": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "3": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "4": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "5": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "6": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "7": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "8": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "9": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "10": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] } } } @@ -357,7 +427,13 @@ #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 - let depths#1 = (_){ _ } + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] } } tree: (struct){ @@ -371,49 +447,7 @@ } cow: (string){ "moo" } } - d: (_|_){ - // [incomplete] issue2052.full.d: cannot add field #maxiter: was already used: - // ./issue2052.cue:143:23 - #maxiter: (int){ |(*(int){ 4 }, (int){ &(>=0, int) }) } - #funcFactory: (#struct){ - #next: (_){ _ } - #func: (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - } - #funcs: (#struct){ - "4": (null){ null } - "0": (_){ _ } - "1": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "2": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - "3": (#struct){ - #in: (_){ _ } - #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } - out: (int){ - 1 - let depths#1 = (_){ _ } - } - } - } + d: (#struct){ #in: (#struct){ a: (#struct){ foo: (string){ "bar" } @@ -425,6 +459,192 @@ } cow: (string){ "moo" } } + #maxiter: (int){ 11 } + #funcFactory: (#struct){ + #next: (_){ _ } + #func: (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + } + #funcs: (#struct){ + "11": (null){ null } + "0": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "1": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "2": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "3": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "4": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "5": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "6": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "7": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "8": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "9": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + "10": (#struct){ + #in: (_){ _ } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 1 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } + } + } + #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } + out: (int){ + 5 + let depths#1multi = [ + for k, v in 〈3;#in〉 { + (〈6;#next〉 & { + #in: 〈2;v〉 + }).out + }, + ] + } } } } -- out/eval/stats -- Leaks: 56 Freed: 1788 Reused: 1774 Allocs: 70 Retain: 174 Unifications: 759 Conjuncts: 3139 Disjuncts: 1942 -- diff/todo/p2 -- issue2052.full.#Recurse: cycle error. This is not the worst, as a self-reference cycle is an incomplete error and more or less equivalent to _, but the same resolution as V2 would be preferential. This is P2, rather than P1, as the result for V3 is already better than V2. -- diff/explanation -- issue2052.full.d.#funcs: v3 has 11 elements, whereas v2 has 4. It seems to me that v3 is correct, 11 is explicitly set in #Depth, which is used in d. -- out/eval -- (struct){ chain: (struct){ t1: (struct){ #maxiter: (int){ 2 } x: (#struct){ } a: (struct){ x2: (null){ null } x0: (#struct){ } x1: (#struct){ } } #DepthF: (#struct){ #in: (_){ _ } #out: (#struct){ } } } t2: (struct){ p1: (struct){ X: (int){ 1 } x: (struct){ x0: (struct){ } x1: (struct){ } } } p2: (_|_){ // [incomplete] chain.t2.p2.0.1: invalid interpolation: cycle error referencing X: // ./in.cue:44:6 // ./in.cue:43:28 x: (_|_){ // [incomplete] chain.t2.p2.0.1: invalid interpolation: cycle error referencing X: // ./in.cue:44:6 // ./in.cue:43:28 x0: (struct){ } } X: (int){ 1 } } } t3: (struct){ p1: (struct){ X: (int){ 1 } x: (struct){ x0: (struct){ } } } } } issue2052: (struct){ reduced: (struct){ t1: (struct){ A: (struct){ a: (_){ _ } } Depth: (struct){ #maxiter: (int){ 1 } funcs: (struct){ "0": (struct){ a: (_){ _ } } } a: (_){ _ } } } t2: (struct){ A: (struct){ a: (_){ _ } } Depth: (struct){ maxiter: (int){ 1 } funcs: (struct){ "0": (struct){ a: (_){ _ } } } a: (_){ _ } } } } medium: (struct){ t1: (struct){ #Depth: (#struct){ #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } #DepthF: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } tree: (string){ "bar" } d: (#struct){ #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #in: (string){ "bar" } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } t2: (struct){ #Depth: (#struct){ #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } #DepthF: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } tree: (string){ "bar" } d: (#struct){ #maxiter: (int){ 4 } #funcs: (#struct){ "4": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } #in: (string){ "bar" } #basic: ((null|string)){ |((string){ string }, (null){ null }) } out: (int){ 1 } } } } full: (struct){ #RecurseN: (_){ _ #maxiter: (int){ |(*(int){ 4 }, (int){ &(>=0, int) }) } #funcFactory: (#struct){ #next: (_){ _ } #func: (_){ _ } } #funcs: (#struct){ "4": (null){ null } "0": (_){ _ } "1": (_){ _ } "2": (_){ _ } "3": (_){ _ } } } #DepthF: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } } #Depth: (#struct){ #maxiter: (int){ 11 } #funcFactory: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } } #funcs: (#struct){ "11": (null){ null } "0": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "1": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "4": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "5": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "6": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "7": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "8": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "9": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "10": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } } #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } tree: (struct){ a: (struct){ foo: (string){ "bar" } a: (struct){ b: (struct){ c: (string){ "d" } } } } cow: (string){ "moo" } } d: (_|_){ // [incomplete] issue2052.full.d: cannot add field #maxiter: was already used: // ./issue2052.cue:143:23 #maxiter: (int){ |(*(int){ 4 }, (int){ &(>=0, int) }) } #funcFactory: (#struct){ #next: (_){ _ } #func: (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } } #funcs: (#struct){ "4": (null){ null } "0": (_){ _ } "1": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "2": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } "3": (#struct){ #in: (_){ _ } #basic: ((null|string|bytes|number)){ |((int){ int }, (number){ number }, (string){ string }, (bytes){ bytes }, (null){ null }) } out: (int){ 1 let depths#1 = (_){ _ } } } } #in: (#struct){ a: (#struct){ foo: (string){ "bar" } a: (#struct){ b: (#struct){ c: (string){ "d" } } } } cow: (string){ "moo" } } } } } } -- out/compile -- --- in.cue { chain: { t1: { #maxiter: 2 x: 〈0;a〉.x0 a: { for k, _ in [ 0, 1, ] { "x\(〈1;k〉)": (〈3;#DepthF〉 & { #in: 〈4;a〉["x\((〈2;k〉 + 1))"] }).#out } } a: { x2: null } #DepthF: { #in: _ #out: {} } } } chain: { t2: { p1: { X: 1 for _, v in 〈import;list〉.Concat([ [ 0, 〈2;X〉, ], [], ]) { x: { "x\(〈2;v〉)": {} } } x: _ 〈0;x〉.x0 } } } chain: { t2: { p2: { for _, v in 〈import;list〉.Concat([ [ 0, 〈2;X〉, ], [], ]) { x: { "x\(〈2;v〉)": {} } } x: _ 〈0;x〉.x0 X: 1 } } } chain: { t3: { p1: { X: 1 for _, v in 〈import;list〉.Range(0, 〈0;X〉, 1) { x: { "x\(〈2;v〉)": {} } } x: _ 〈0;x〉.x0 } } } chain: { t3: { p1: { for _, v in 〈import;list〉.Range(0, 〈0;X〉, 1) { x: { "x\(〈2;v〉)": {} } } x: _ 〈0;x〉.x0 X: 1 } } } } --- issue2052.cue { issue2052: { reduced: { t1: { A: { a: _ } Depth: { #maxiter: 1 if (〈import;math〉.Abs(〈0;#maxiter〉) == 1) { funcs: { "\(0)": 〈3;A〉 } } funcs: {} 〈0;funcs〉["0"] } } } } issue2052: { reduced: { t2: { A: { a: _ } Depth: { maxiter: 1 for k, v in 〈import;list〉.Range(0, 〈0;maxiter〉, 1) { funcs: { "\(0)": 〈4;A〉 } } funcs: {} 〈0;funcs〉["0"] } } } } issue2052: { medium: { t1: { #Depth: { #maxiter: 4 for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { #funcs: { "\(〈2;k〉)": (〈4;#DepthF〉 & { #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] }).#func } } #funcs: { "\(〈1;#maxiter〉)": null } 〈0;#funcs〉["0"] } #DepthF: { #next: _ #func: { #in: _ #basic: (string|null) out: { if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { 1 } if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { (〈import;list〉.Max([ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ]) + 1) } } } } tree: "bar" d: (〈0;#Depth〉 & { #in: 〈1;tree〉 }) } } } issue2052: { medium: { t2: { #Depth: { #maxiter: 4 for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { #funcs: { "\(〈2;k〉)": (〈4;#DepthF〉 & { #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] }).#func } } #funcs: { for k, v in 〈import;list〉.Range(0, 〈1;#maxiter〉, 1) { "\(〈1;k〉)": (〈4;#DepthF〉 & { #next: 〈4;#funcs〉["\((〈2;k〉 + 1))"] }).#func } } #funcs: { "\(〈1;#maxiter〉)": null } 〈0;#funcs〉["0"] } #DepthF: { #next: _ #func: { #in: _ #basic: (string|null) out: { if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { 1 } if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { (〈import;list〉.Max([ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ]) + 1) } } } } tree: "bar" d: (〈0;#Depth〉 & { #in: 〈1;tree〉 }) } } } issue2052: { full: { #RecurseN: { #maxiter: (&(int, >=0)|*4) #funcFactory: { #next: _ #func: _ } for k, v in 〈import;list〉.Range(0, 〈0;#maxiter〉, 1) { #funcs: { "\(〈2;k〉)": (〈3;#funcFactory〉 & { #next: 〈2;#funcs〉["\((〈3;k〉 + 1))"] }).#func } } #funcs: { "\(〈1;#maxiter〉)": null } 〈0;#funcs〉["0"] } #DepthF: { #next: _ #func: { #in: _ #basic: (int|number|string|bytes|null) out: { if ((〈1;#in〉 & 〈1;#basic〉) != _|_(explicit error (_|_ literal) in source)) { 1 } if ((〈1;#in〉 & 〈1;#basic〉) == _|_(explicit error (_|_ literal) in source)) { let depths#1 = [ for k, v in 〈3;#in〉 { (〈6;#next〉 & { #in: 〈2;v〉 }).out }, ] (〈import;list〉.Max(〈0;let depths#1〉) + 1) } } } } #Depth: (〈0;#RecurseN〉 & { #maxiter: 11 #funcFactory: 〈1;#DepthF〉 }) tree: { a: { foo: "bar" a: { b: { c: "d" } } } cow: "moo" } d: (〈0;#Depth〉 & { #in: 〈1;tree〉 }) } } } cue-lang-cue-db9cc73/cue/testdata/cycle/compbottom.txtar000066400000000000000000000421201474664451600234320ustar00rootroot00000000000000// Issues: #667, #695, #622 // Comparing against bottom is not officially supported by the spec. // In practice it is used for a variety of purposes. // // TODO: It should really be replaced with two builtins: // // - exists(reference): check if a certain field exists. // - isvalid(value): check if a certain value is valid (recursively). // // For now it implements something in between these two: it fails if a value // resolves to an error, but not necessarily if it does so recursively. // Although adding a recursive check is easy, it will break existing // configurations, as a recursive evaluation will trigger cycles where these // are perhaps not expected. // To verify these tests, each result should have a field // // X: "user@example.com" // // for the large and medium examples and // // X: "message: hello" // // for the simple example. // // These are not automatically tested using CUE to avoid interfering with the // evaluation. -- in.cue -- import "regexp" simple: { #message: #"^(message: (?P.*))?$"# p1: { X: "message: hello" #aux: { if Y.message == _|_ { message: "" } if Y.message != _|_ { message: "message: " + Y.message } } Y: regexp.FindNamedSubmatch(#message, X) X: #aux.message } p2: { #aux: { if Y.message == _|_ { message: "" } if Y.message != _|_ { message: "message: " + Y.message } } X: "message: hello" Y: regexp.FindNamedSubmatch(#message, X) X: #aux.message } p3: { #aux: { if Y.message == _|_ { message: "" } if Y.message != _|_ { message: "message: " + Y.message } } Y: regexp.FindNamedSubmatch(#message, X) X: "message: hello" X: #aux.message } p4: { X: #aux.message #aux: { if Y.message == _|_ { message: "" } if Y.message != _|_ { message: "message: " + Y.message } } Y: regexp.FindNamedSubmatch(#message, X) X: "message: hello" } p5: { #aux: { if Y.message == _|_ { message: "" } if Y.message != _|_ { message: "message: " + Y.message } } X: #aux.message Y: regexp.FindNamedSubmatch(#message, X) X: "message: hello" } p6: { #aux: { if Y.message == _|_ { message: "" } if Y.message != _|_ { message: "message: " + Y.message } } Y: regexp.FindNamedSubmatch(#message, X) X: #aux.message X: "message: hello" } } medium: { #userHostPort: #"^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$"# p1: { Y: { userinfo: "user" host: "mod.test" } // X: "user@example.com" X: #X.userinfo + #X.host #X: { // userinfo: "user@" // host: "mod.test" if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host } Y: { // userinfo: "user" // host: "mod.test" if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host } #Y: regexp.FindNamedSubmatch(#userHostPort, X) } p2: { X: #X.userinfo + #X.host Y: { userinfo: "user" host: "mod.test" } #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host } #Y: regexp.FindNamedSubmatch(#userHostPort, X) } p3: { X: #X.userinfo + #X.host #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host } Y: { userinfo: "user" host: "mod.test" } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host } #Y: regexp.FindNamedSubmatch(#userHostPort, X) } p4: { X: #X.userinfo + #X.host #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host } #Y: regexp.FindNamedSubmatch(#userHostPort, X) Y: { userinfo: "user" host: "mod.test" } } } -- out/eval/stats -- Leaks: 0 Freed: 85 Reused: 73 Allocs: 12 Retain: 200 Unifications: 85 Conjuncts: 152 Disjuncts: 194 -- out/evalalpha -- (struct){ simple: (struct){ #message: (string){ "^(message: (?P.*))?$" } p1: (struct){ X: (string){ "message: hello" } #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } } p2: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } X: (string){ "message: hello" } Y: (struct){ message: (string){ "hello" } } } p3: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } X: (string){ "message: hello" } } p4: (struct){ X: (string){ "message: hello" } #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } } p5: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } X: (string){ "message: hello" } Y: (struct){ message: (string){ "hello" } } } p6: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } X: (string){ "message: hello" } } } medium: (struct){ #userHostPort: (string){ "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$" } p1: (struct){ Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } X: (string){ "user@mod.test" } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (#struct){ host: (string){ "mod.test" } userinfo: (string){ "user" } } } p2: (struct){ X: (string){ "user@mod.test" } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (#struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } } p3: (struct){ X: (string){ "user@mod.test" } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #Y: (#struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } } p4: (struct){ X: (string){ "user@mod.test" } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #Y: (#struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -84,38 +84,38 @@ host: (string){ "mod.test" } } #Y: (#struct){ - host: (string){ "mod.test" } - userinfo: (string){ "user" } - } - } - p3: (struct){ - X: (string){ "user@mod.test" } - #X: (#struct){ - userinfo: (string){ "user@" } - host: (string){ "mod.test" } - } - Y: (struct){ - userinfo: (string){ "user" } - host: (string){ "mod.test" } - } - #Y: (#struct){ - host: (string){ "mod.test" } - userinfo: (string){ "user" } - } - } - p4: (struct){ - X: (string){ "user@mod.test" } - #X: (#struct){ - userinfo: (string){ "user@" } - host: (string){ "mod.test" } - } - Y: (struct){ - userinfo: (string){ "user" } - host: (string){ "mod.test" } - } - #Y: (#struct){ - host: (string){ "mod.test" } - userinfo: (string){ "user" } + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + } + p3: (struct){ + X: (string){ "user@mod.test" } + #X: (#struct){ + userinfo: (string){ "user@" } + host: (string){ "mod.test" } + } + Y: (struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + #Y: (#struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + } + p4: (struct){ + X: (string){ "user@mod.test" } + #X: (#struct){ + userinfo: (string){ "user@" } + host: (string){ "mod.test" } + } + Y: (struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + #Y: (#struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } } } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ simple: (struct){ #message: (string){ "^(message: (?P.*))?$" } p1: (struct){ X: (string){ "message: hello" } #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } } p2: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } X: (string){ "message: hello" } Y: (struct){ message: (string){ "hello" } } } p3: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } X: (string){ "message: hello" } } p4: (struct){ X: (string){ "message: hello" } #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } } p5: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } X: (string){ "message: hello" } Y: (struct){ message: (string){ "hello" } } } p6: (struct){ #aux: (#struct){ message: (string){ "message: hello" } } Y: (struct){ message: (string){ "hello" } } X: (string){ "message: hello" } } } medium: (struct){ #userHostPort: (string){ "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$" } p1: (struct){ Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } X: (string){ "user@mod.test" } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (#struct){ host: (string){ "mod.test" } userinfo: (string){ "user" } } } p2: (struct){ X: (string){ "user@mod.test" } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (#struct){ host: (string){ "mod.test" } userinfo: (string){ "user" } } } p3: (struct){ X: (string){ "user@mod.test" } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #Y: (#struct){ host: (string){ "mod.test" } userinfo: (string){ "user" } } } p4: (struct){ X: (string){ "user@mod.test" } #X: (#struct){ userinfo: (string){ "user@" } host: (string){ "mod.test" } } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #Y: (#struct){ host: (string){ "mod.test" } userinfo: (string){ "user" } } } } } -- out/compile -- --- in.cue { simple: { #message: "^(message: (?P.*))?$" p1: { X: "message: hello" #aux: { if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { message: "" } if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { message: ("message: " + 〈2;Y〉.message) } } Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) X: 〈0;#aux〉.message } p2: { #aux: { if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { message: "" } if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { message: ("message: " + 〈2;Y〉.message) } } X: "message: hello" Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) X: 〈0;#aux〉.message } p3: { #aux: { if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { message: "" } if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { message: ("message: " + 〈2;Y〉.message) } } Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) X: "message: hello" X: 〈0;#aux〉.message } p4: { X: 〈0;#aux〉.message #aux: { if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { message: "" } if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { message: ("message: " + 〈2;Y〉.message) } } Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) X: "message: hello" } p5: { #aux: { if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { message: "" } if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { message: ("message: " + 〈2;Y〉.message) } } X: 〈0;#aux〉.message Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) X: "message: hello" } p6: { #aux: { if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) { message: "" } if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) { message: ("message: " + 〈2;Y〉.message) } } Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉) X: 〈0;#aux〉.message X: "message: hello" } } medium: { #userHostPort: "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)$" p1: { Y: { userinfo: "user" host: "mod.test" } X: (〈0;#X〉.userinfo + 〈0;#X〉.host) #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) } p2: { X: (〈0;#X〉.userinfo + 〈0;#X〉.host) Y: { userinfo: "user" host: "mod.test" } #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) } p3: { X: (〈0;#X〉.userinfo + 〈0;#X〉.host) #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host } Y: { userinfo: "user" host: "mod.test" } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) } p4: { X: (〈0;#X〉.userinfo + 〈0;#X〉.host) #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) Y: { userinfo: "user" host: "mod.test" } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/compbottom2.txtar000066400000000000000000000657701474664451600235340ustar00rootroot00000000000000-- in.cue -- self: { // This is an incomplete error, as it may succeed when the user // explicitly specifies a value for fail.a.b. fail: { a: { if a.b == _|_ { b: 1 } } } // This is an incomplete error, as it may succeed when the user // explicitly specifies a value for a.b. isConcreteFail: t1:{ a: { if a.b == _|_ { b: 1 } b: int } } isConcreteFail: t2:{ a: { if a.b == _|_ { b: 1 } b?: int } } // This is an incomplete error, as it may succeed when the user // explicitly specifies a value for a.b. // TODO: new builtin semantics. // if isconcrete(a.b) -->> cyclic error evaluating isconcrete. // if isdefined(a.b) -->> evaluate to true as a.b is int, result is 1 // if !isdefined(a.b) -->> evaluate to false, a.b remains int isNotConcrete: t1: { a: { if a.b != _|_ { b: 1 } b: int } } isNotConcrete: t2: { a: { if a.b != _|_ { b: 1 } b?: int } } } -- mutual.cue -- mutual: { noConflicts: { a: {if b.foo == _|_ {new: ""}} b: {if a.bar == _|_ {new: ""}} } mutualCycleFail: { b: {if a.bar == _|_ {foo: ""}} a: {if b.foo == _|_ {bar: ""}} } brokenCycleSuccess: { a: { if b.foo == _|_ { foo: "" } } b: { if a.bar == _|_ { bar: "" } } a: bar: "" } allowOneDirectionalDependency: { p1: { a: { if b.foo == _|_ { bar: "" } } // added b: { if a.bar == _|_ { new: "" } } // not added } p2: { a: { if b.foo == _|_ { new: "" } } b: { if a.bar == _|_ { foo: "" } } } } oneDirectionalBrokenConflictSuccess: p1: { b: foo: "" a: { if b.foo == _|_ { bar: "" } } b: { if a.bar == _|_ { new: "" } } } oneDirectionalBrokenConflictSuccess: p2: { a: { if b.foo == _|_ { bar: "" } } b: foo: "" b: { if a.bar == _|_ { new: "" } } } oneDirectionalBrokenConflictSuccess: p3: { a: { if b.foo == _|_ { bar: "" } } b: { if a.bar == _|_ { new: "" } } b: foo: "" } oneDirectionalBrokenConflictSuccess: p4: { b: foo: "" b: { if a.bar == _|_ { new: "" } } a: { if b.foo == _|_ { bar: "" } } } oneDirectionalBrokenConflictSuccess: p5: { b: { if a.bar == _|_ { new: "" } } b: foo: "" a: { if b.foo == _|_ { bar: "" } } } oneDirectionalBrokenConflictSuccess: p6: { b: { if a.bar == _|_ { new: "" } } a: { if b.foo == _|_ { bar: "" } } b: foo: "" } } -- mutualsamestruct.cue -- sameStruct: { chainSuccess: a: { raises?: {} if raises == _|_ { ret: a: 1 } ret?: {} if ret != _|_ { foo: a: 1 } } chainSuccess: b: { if ret != _|_ { foo: a: 1 } raises?: {} if raises == _|_ { ret: a: 1 } ret?: {} } cycleFail: t1: p1: { raises?: {} if raises == _|_ { ret: a: 1 } ret?: {} if ret != _|_ { raises: a: 1 } } cycleFail: t1: p2: { ret?: {} if ret != _|_ { raises: a: 1 } raises?: {} if raises == _|_ { ret: a: 1 } } // This test should fail with a cycle error. Even though raises and ret are // both known to be defined, comparison against bottom requires that the // structs be recursively checked for errors. We disallow that here, because // the structs mutually depend on each other. // TODO: consider allowing a specific postCheck for determining if an arc // is erroneous. cycleFail: t2: p1: { raises: {} if raises == _|_ { ret: a: 1 } ret: {} if ret != _|_ { raises: a: 1 } } // Same as above test, but different order. It may be that the specific // fields that are added are different for the two cases. This is fine as // long as the parent fails, as that error is ultimately what represents // the value as a whole. cycleFail: t2: p2: { ret: {} if ret != _|_ { raises: a: 1 } raises: {} if raises == _|_ { ret: a: 1 } } // This test should fail similarly to the above tests. The fields ret and // raises are not concrete, but may still become a struct and thus need // to be recursively checked. cycleFail: t3: p1: { raises: _ if raises == _|_ { ret: a: 1 } ret: _ if ret != _|_ { raises: a: 1 } } cycleFail: t3: p2: { ret: _ if ret != _|_ { raises: a: 1 } raises: _ if raises == _|_ { ret: a: 1 } } defCloseSuccess: { #Example: { raises?: { runtime?: string } if raises == _|_ { ret?: _ } } expr: #Example & { ret: 2 } } } -- nestedchain.cue -- // Issue nestedChain: { cycleFail: { if #E.x != _|_ { #E: y: true } if #E.y == _|_ { #E: x: true } #E: [_]: bool } brokenCycleSuccess: { if #E.x != _|_ { #E: y: true } if #E.y == _|_ { #E: x: true } #E: [_]: bool #E: x: true } doubleAddfail: { if #E.x == _|_ { #E: y: true } if #E.y == _|_ { #E: x: true } #E: [_]: bool } trippleSuccess: { if #E.x != _|_ { #E: y: true } if #E.y != _|_ { z: true } #E: x: true } } -- out/eval/stats -- Leaks: 1 Freed: 158 Reused: 149 Allocs: 10 Retain: 67 Unifications: 159 Conjuncts: 169 Disjuncts: 204 -- out/evalalpha -- (struct){ self: (struct){ fail: (struct){ a: (_|_){ // [incomplete] self.fail.a.b: cyclic reference to field b: // ./in.cue:6:4 } } isConcreteFail: (struct){ t1: (struct){ a: (struct){ b: (int){ 1 } } } t2: (struct){ a: (_|_){ // [cycle] self.isConcreteFail.t2.a: circular dependency in evaluation of conditionals: a.b changed after evaluation: // ./in.cue:25:7 } } } isNotConcrete: (struct){ t1: (struct){ a: (struct){ b: (int){ int } } } t2: (struct){ a: (struct){ b?: (int){ int } } } } } mutual: (struct){ noConflicts: (struct){ a: (struct){ new: (string){ "" } } b: (struct){ new: (string){ "" } } } mutualCycleFail: (struct){ b: (_|_){ // [incomplete] mutual.mutualCycleFail.b.foo: cyclic reference to field foo: // ./mutual.cue:8:7 } a: (_|_){ // [incomplete] mutual.mutualCycleFail.a.bar: cyclic reference to field bar: // ./mutual.cue:9:7 } } brokenCycleSuccess: (struct){ a: (struct){ foo: (string){ "" } bar: (string){ "" } } b: (struct){ } } allowOneDirectionalDependency: (struct){ p1: (struct){ a: (struct){ bar: (string){ "" } } b: (struct){ } } p2: (struct){ a: (struct){ } b: (struct){ foo: (string){ "" } } } } oneDirectionalBrokenConflictSuccess: (struct){ p1: (struct){ b: (struct){ foo: (string){ "" } new: (string){ "" } } a: (struct){ } } p2: (struct){ a: (struct){ } b: (struct){ foo: (string){ "" } new: (string){ "" } } } p3: (struct){ a: (struct){ } b: (struct){ new: (string){ "" } foo: (string){ "" } } } p4: (struct){ b: (struct){ foo: (string){ "" } new: (string){ "" } } a: (struct){ } } p5: (struct){ b: (struct){ new: (string){ "" } foo: (string){ "" } } a: (struct){ } } p6: (struct){ b: (struct){ new: (string){ "" } foo: (string){ "" } } a: (struct){ } } } } sameStruct: (struct){ chainSuccess: (struct){ a: (struct){ raises?: (struct){ } ret: (struct){ a: (int){ 1 } } foo: (struct){ a: (int){ 1 } } } b: (struct){ foo: (struct){ a: (int){ 1 } } raises?: (struct){ } ret: (struct){ a: (int){ 1 } } } } cycleFail: (struct){ t1: (struct){ p1: (_|_){ // [cycle] sameStruct.cycleFail.t1.p1: circular dependency in evaluation of conditionals: raises changed after evaluation: // ./mutualsamestruct.cue:26:6 } p2: (_|_){ // [cycle] sameStruct.cycleFail.t1.p2: circular dependency in evaluation of conditionals: ret changed after evaluation: // ./mutualsamestruct.cue:37:6 } } t2: (struct){ p1: (_|_){ // [cycle] sameStruct.cycleFail.t2.p1: circular dependency in evaluation of conditionals: raises changed after evaluation: // ./mutualsamestruct.cue:54:6 } p2: (_|_){ // [cycle] sameStruct.cycleFail.t2.p2: circular dependency in evaluation of conditionals: ret changed after evaluation: // ./mutualsamestruct.cue:69:6 } } t3: (struct){ p1: (_|_){ // [cycle] sameStruct.cycleFail.t3.p1: circular dependency in evaluation of conditionals: raises changed after evaluation: // ./mutualsamestruct.cue:83:6 } p2: (_|_){ // [cycle] sameStruct.cycleFail.t3.p2: circular dependency in evaluation of conditionals: ret changed after evaluation: // ./mutualsamestruct.cue:94:6 } } } defCloseSuccess: (struct){ #Example: (#struct){ raises?: (#struct){ runtime?: (string){ string } } ret?: (_){ _ } } expr: (#struct){ ret: (int){ 2 } raises?: (#struct){ runtime?: (string){ string } } } } } nestedChain: (struct){ cycleFail: (_|_){ // [incomplete] nestedChain.cycleFail.#E.x: cyclic reference to field x: // ./nestedchain.cue:7:3 #E: (#struct){ } } brokenCycleSuccess: (struct){ #E: (#struct){ y: (bool){ true } x: (bool){ true } } } doubleAddfail: (_|_){ // [incomplete] nestedChain.doubleAddfail.#E.y: cyclic reference to field y: // ./nestedchain.cue:25:3 // nestedChain.doubleAddfail.#E.x: cyclic reference to field x: // ./nestedchain.cue:28:3 #E: (#struct){ } } trippleSuccess: (struct){ #E: (#struct){ y: (bool){ true } x: (bool){ true } } z: (bool){ true } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,14 +2,14 @@ self: (struct){ fail: (struct){ a: (_|_){ - // [cycle] self.fail.a: cycle with field a.b: - // ./in.cue:6:7 + // [incomplete] self.fail.a.b: cyclic reference to field b: + // ./in.cue:6:4 } } isConcreteFail: (struct){ t1: (struct){ - a: (_|_){ - // [cycle] cycle error + a: (struct){ + b: (int){ 1 } } } t2: (struct){ @@ -21,8 +21,8 @@ } isNotConcrete: (struct){ t1: (struct){ - a: (_|_){ - // [cycle] cycle error + a: (struct){ + b: (int){ int } } } t2: (struct){ @@ -43,12 +43,12 @@ } mutualCycleFail: (struct){ b: (_|_){ - // [cycle] mutual.mutualCycleFail.a: cycle with field b.foo: - // ./mutual.cue:9:10 - } - a: (_|_){ - // [cycle] mutual.mutualCycleFail.a: cycle with field b.foo: - // ./mutual.cue:9:10 + // [incomplete] mutual.mutualCycleFail.b.foo: cyclic reference to field foo: + // ./mutual.cue:8:7 + } + a: (_|_){ + // [incomplete] mutual.mutualCycleFail.a.bar: cyclic reference to field bar: + // ./mutual.cue:9:7 } } brokenCycleSuccess: (struct){ @@ -189,17 +189,19 @@ ret?: (_){ _ } } expr: (#struct){ - raises?: (#struct){ - runtime?: (string){ string } - } ret: (int){ 2 } + raises?: (#struct){ + runtime?: (string){ string } + } } } } nestedChain: (struct){ cycleFail: (_|_){ - // [cycle] nestedChain.cycleFail: cycle with field #E.y: - // ./nestedchain.cue:7:6 + // [incomplete] nestedChain.cycleFail.#E.x: cyclic reference to field x: + // ./nestedchain.cue:7:3 + #E: (#struct){ + } } brokenCycleSuccess: (struct){ #E: (#struct){ @@ -208,8 +210,12 @@ } } doubleAddfail: (_|_){ - // [cycle] nestedChain.doubleAddfail: cycle with field #E.y: - // ./nestedchain.cue:28:6 + // [incomplete] nestedChain.doubleAddfail.#E.y: cyclic reference to field y: + // ./nestedchain.cue:25:3 + // nestedChain.doubleAddfail.#E.x: cyclic reference to field x: + // ./nestedchain.cue:28:3 + #E: (#struct){ + } } trippleSuccess: (struct){ #E: (#struct){ -- diff/explanation -- self.isConcreteFail: t1: int value is not an error. self.isNotConcrete: t1: int value is not an error. -- out/eval -- (struct){ self: (struct){ fail: (struct){ a: (_|_){ // [cycle] self.fail.a: cycle with field a.b: // ./in.cue:6:7 } } isConcreteFail: (struct){ t1: (struct){ a: (_|_){ // [cycle] cycle error } } t2: (struct){ a: (_|_){ // [cycle] self.isConcreteFail.t2.a: circular dependency in evaluation of conditionals: a.b changed after evaluation: // ./in.cue:25:7 } } } isNotConcrete: (struct){ t1: (struct){ a: (_|_){ // [cycle] cycle error } } t2: (struct){ a: (struct){ b?: (int){ int } } } } } mutual: (struct){ noConflicts: (struct){ a: (struct){ new: (string){ "" } } b: (struct){ new: (string){ "" } } } mutualCycleFail: (struct){ b: (_|_){ // [cycle] mutual.mutualCycleFail.a: cycle with field b.foo: // ./mutual.cue:9:10 } a: (_|_){ // [cycle] mutual.mutualCycleFail.a: cycle with field b.foo: // ./mutual.cue:9:10 } } brokenCycleSuccess: (struct){ a: (struct){ foo: (string){ "" } bar: (string){ "" } } b: (struct){ } } allowOneDirectionalDependency: (struct){ p1: (struct){ a: (struct){ bar: (string){ "" } } b: (struct){ } } p2: (struct){ a: (struct){ } b: (struct){ foo: (string){ "" } } } } oneDirectionalBrokenConflictSuccess: (struct){ p1: (struct){ b: (struct){ foo: (string){ "" } new: (string){ "" } } a: (struct){ } } p2: (struct){ a: (struct){ } b: (struct){ foo: (string){ "" } new: (string){ "" } } } p3: (struct){ a: (struct){ } b: (struct){ new: (string){ "" } foo: (string){ "" } } } p4: (struct){ b: (struct){ foo: (string){ "" } new: (string){ "" } } a: (struct){ } } p5: (struct){ b: (struct){ new: (string){ "" } foo: (string){ "" } } a: (struct){ } } p6: (struct){ b: (struct){ new: (string){ "" } foo: (string){ "" } } a: (struct){ } } } } sameStruct: (struct){ chainSuccess: (struct){ a: (struct){ raises?: (struct){ } ret: (struct){ a: (int){ 1 } } foo: (struct){ a: (int){ 1 } } } b: (struct){ foo: (struct){ a: (int){ 1 } } raises?: (struct){ } ret: (struct){ a: (int){ 1 } } } } cycleFail: (struct){ t1: (struct){ p1: (_|_){ // [cycle] sameStruct.cycleFail.t1.p1: circular dependency in evaluation of conditionals: raises changed after evaluation: // ./mutualsamestruct.cue:26:6 } p2: (_|_){ // [cycle] sameStruct.cycleFail.t1.p2: circular dependency in evaluation of conditionals: ret changed after evaluation: // ./mutualsamestruct.cue:37:6 } } t2: (struct){ p1: (_|_){ // [cycle] sameStruct.cycleFail.t2.p1: circular dependency in evaluation of conditionals: raises changed after evaluation: // ./mutualsamestruct.cue:54:6 } p2: (_|_){ // [cycle] sameStruct.cycleFail.t2.p2: circular dependency in evaluation of conditionals: ret changed after evaluation: // ./mutualsamestruct.cue:69:6 } } t3: (struct){ p1: (_|_){ // [cycle] sameStruct.cycleFail.t3.p1: circular dependency in evaluation of conditionals: raises changed after evaluation: // ./mutualsamestruct.cue:83:6 } p2: (_|_){ // [cycle] sameStruct.cycleFail.t3.p2: circular dependency in evaluation of conditionals: ret changed after evaluation: // ./mutualsamestruct.cue:94:6 } } } defCloseSuccess: (struct){ #Example: (#struct){ raises?: (#struct){ runtime?: (string){ string } } ret?: (_){ _ } } expr: (#struct){ raises?: (#struct){ runtime?: (string){ string } } ret: (int){ 2 } } } } nestedChain: (struct){ cycleFail: (_|_){ // [cycle] nestedChain.cycleFail: cycle with field #E.y: // ./nestedchain.cue:7:6 } brokenCycleSuccess: (struct){ #E: (#struct){ y: (bool){ true } x: (bool){ true } } } doubleAddfail: (_|_){ // [cycle] nestedChain.doubleAddfail: cycle with field #E.y: // ./nestedchain.cue:28:6 } trippleSuccess: (struct){ #E: (#struct){ y: (bool){ true } x: (bool){ true } } z: (bool){ true } } } } -- out/compile -- --- in.cue { self: { fail: { a: { if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { b: 1 } } } isConcreteFail: { t1: { a: { if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { b: 1 } b: int } } } isConcreteFail: { t2: { a: { if (〈1;a〉.b == _|_(explicit error (_|_ literal) in source)) { b: 1 } b?: int } } } isNotConcrete: { t1: { a: { if (〈1;a〉.b != _|_(explicit error (_|_ literal) in source)) { b: 1 } b: int } } } isNotConcrete: { t2: { a: { if (〈1;a〉.b != _|_(explicit error (_|_ literal) in source)) { b: 1 } b?: int } } } } } --- mutual.cue { mutual: { noConflicts: { a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { new: "" } } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } } mutualCycleFail: { b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { foo: "" } } a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } } brokenCycleSuccess: { a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { foo: "" } } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { bar: "" } } a: { bar: "" } } allowOneDirectionalDependency: { p1: { a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } } p2: { a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { new: "" } } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { foo: "" } } } } oneDirectionalBrokenConflictSuccess: { p1: { b: { foo: "" } a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } } } oneDirectionalBrokenConflictSuccess: { p2: { a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } b: { foo: "" } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } } } oneDirectionalBrokenConflictSuccess: { p3: { a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } b: { foo: "" } } } oneDirectionalBrokenConflictSuccess: { p4: { b: { foo: "" } b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } } } oneDirectionalBrokenConflictSuccess: { p5: { b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } b: { foo: "" } a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } } } oneDirectionalBrokenConflictSuccess: { p6: { b: { if (〈1;a〉.bar == _|_(explicit error (_|_ literal) in source)) { new: "" } } a: { if (〈1;b〉.foo == _|_(explicit error (_|_ literal) in source)) { bar: "" } } b: { foo: "" } } } } } --- mutualsamestruct.cue { sameStruct: { chainSuccess: { a: { raises?: {} if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } ret?: {} if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { foo: { a: 1 } } } } chainSuccess: { b: { if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { foo: { a: 1 } } raises?: {} if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } ret?: {} } } cycleFail: { t1: { p1: { raises?: {} if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } ret?: {} if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { raises: { a: 1 } } } } } cycleFail: { t1: { p2: { ret?: {} if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { raises: { a: 1 } } raises?: {} if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } } } } cycleFail: { t2: { p1: { raises: {} if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } ret: {} if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { raises: { a: 1 } } } } } cycleFail: { t2: { p2: { ret: {} if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { raises: { a: 1 } } raises: {} if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } } } } cycleFail: { t3: { p1: { raises: _ if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } ret: _ if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { raises: { a: 1 } } } } } cycleFail: { t3: { p2: { ret: _ if (〈0;ret〉 != _|_(explicit error (_|_ literal) in source)) { raises: { a: 1 } } raises: _ if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret: { a: 1 } } } } } defCloseSuccess: { #Example: { raises?: { runtime?: string } if (〈0;raises〉 == _|_(explicit error (_|_ literal) in source)) { ret?: _ } } expr: (〈0;#Example〉 & { ret: 2 }) } } } --- nestedchain.cue { nestedChain: { cycleFail: { if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { #E: { y: true } } if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { #E: { x: true } } #E: { [_]: bool } } brokenCycleSuccess: { if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { #E: { y: true } } if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { #E: { x: true } } #E: { [_]: bool } #E: { x: true } } doubleAddfail: { if (〈0;#E〉.x == _|_(explicit error (_|_ literal) in source)) { #E: { y: true } } if (〈0;#E〉.y == _|_(explicit error (_|_ literal) in source)) { #E: { x: true } } #E: { [_]: bool } } trippleSuccess: { if (〈0;#E〉.x != _|_(explicit error (_|_ literal) in source)) { #E: { y: true } } if (〈0;#E〉.y != _|_(explicit error (_|_ literal) in source)) { z: true } #E: { x: true } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/compbottomnofinal.txtar000066400000000000000000001105571474664451600250130ustar00rootroot00000000000000// Issues: #667, #695, #622 -- in.cue -- import ( "strconv" "regexp" ) // In these test, it is impossible to determine the existence of some arcs due // to mutual dependence on becoming concrete. // // This tests shows the essences of when an existence check cannot be resolved. minimal: { a: { if b.port == _|_ { port: "" } } b: { if a.port == _|_ { port: "" } } } small: { #userHostPort: #"^(:(?P\d+))?$"# p1: { #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) #X: { if #Y.port == _|_ { port: "" } if #Y.port != _|_ { port: ":" + strconv.FormatInt(#Y.port, 10) } } } p2: { #X: { if #Y.port == _|_ { port: "" } if #Y.port != _|_ { port: ":" + strconv.FormatInt(#Y.port, 10) } } #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) } } medium: { #userHostPort: #"^(:(?P\d+))?$"# p1: { #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) Y: { if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #X: { // Can never determine whether Y.port exists as its resolution // depends on #Y becoming finalized, which, in turn, depends on #X // becoming finalized. if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } } p2: { #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) #X: { // Can never determine whether Y.port exists as its resolution // depends on #Y becoming finalized, which, in turn, depends on #X // becoming finalized. if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } Y: { if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } } p3: { Y: { if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) #X: { // Can never determine whether Y.port exists as its resolution // depends on #Y becoming finalized, which, in turn, depends on #X // becoming finalized. if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } } p4: { Y: { if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #X: { // Can never determine whether Y.port exists as its resolution // depends on #Y becoming finalized, which, in turn, depends on #X // becoming finalized. if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) } p5: { #X: { // Can never determine whether Y.port exists as its resolution // depends on #Y becoming finalized, which, in turn, depends on #X // becoming finalized. if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) Y: { if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } } p6: { #X: { // Can never determine whether Y.port exists as its resolution // depends on #Y becoming finalized, which, in turn, depends on #X // becoming finalized. if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } Y: { if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #Y: regexp.FindNamedSubmatch(#userHostPort, #X.port) } } large: { #userHostPort: #"^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\d+))?$"# p1: { Y: { userinfo: "user" host: "mod.test" } X: #X.userinfo + #X.host + #X.port #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #Y: regexp.FindNamedSubmatch(#userHostPort, X) } p2: { X: #X.userinfo + #X.host + #X.port Y: { userinfo: "user" host: "mod.test" } #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #Y: regexp.FindNamedSubmatch(#userHostPort, X) } p3: { X: #X.userinfo + #X.host + #X.port #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } Y: { userinfo: "user" host: "mod.test" } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } #Y: regexp.FindNamedSubmatch(#userHostPort, X) } p4: { X: #X.userinfo + #X.host + #X.port #X: { if Y.userinfo == _|_ { userinfo: "" } if Y.userinfo != _|_ { userinfo: Y.userinfo + "@" } host: Y.host if Y.port == _|_ { port: "" } if Y.port != _|_ { port: ":" + strconv.FormatInt(Y.port, 10) } } #Y: regexp.FindNamedSubmatch(#userHostPort, X) Y: { userinfo: "user" host: "mod.test" } Y: { if #Y.userinfo != _|_ { userinfo: #Y.userinfo } host: #Y.host if #Y.port != _|_ { port: strconv.Atoi(#Y.port) } } } } -- out/eval/stats -- Leaks: 10 Freed: 105 Reused: 95 Allocs: 20 Retain: 302 Unifications: 115 Conjuncts: 244 Disjuncts: 215 -- out/evalalpha -- (struct){ minimal: (struct){ a: (_|_){ // [incomplete] minimal.a.port: cyclic reference to field port: // ./in.cue:12:3 } b: (_|_){ // [incomplete] minimal.b.port: cyclic reference to field port: // ./in.cue:18:3 } } small: (struct){ #userHostPort: (string){ "^(:(?P\\d+))?$" } p1: (struct){ #Y: (_|_){ // [incomplete] small.p1.#Y: undefined field: port: // ./in.cue:28:50 } #X: (_|_){ // [incomplete] small.p1.#X.port: cyclic reference to field port: // ./in.cue:31:4 } } p2: (struct){ #X: (_|_){ // [incomplete] small.p2.#X.port: cyclic reference to field port: // ./in.cue:42:4 } #Y: (_|_){ // [incomplete] small.p2.#Y: undefined field: port: // ./in.cue:50:50 } } } medium: (struct){ #userHostPort: (string){ "^(:(?P\\d+))?$" } p1: (struct){ #Y: (_|_){ // [incomplete] medium.p1.#Y: undefined field: port: // ./in.cue:58:50 } Y: (struct){ } #X: (_|_){ // [incomplete] medium.p1.#X.port: cyclic reference to field port: // ./in.cue:70:4 } } p2: (struct){ #Y: (_|_){ // [incomplete] medium.p2.#Y: undefined field: port: // ./in.cue:80:50 } #X: (_|_){ // [incomplete] medium.p2.#X.port: cyclic reference to field port: // ./in.cue:86:4 } Y: (struct){ } } p3: (struct){ Y: (struct){ } #Y: (_|_){ // [incomplete] medium.p3.#Y: undefined field: port: // ./in.cue:108:50 } #X: (_|_){ // [incomplete] medium.p3.#X.port: cyclic reference to field port: // ./in.cue:114:4 } } p4: (struct){ Y: (struct){ } #X: (_|_){ // [incomplete] medium.p4.#X.port: cyclic reference to field port: // ./in.cue:134:4 } #Y: (_|_){ // [incomplete] medium.p4.#Y: undefined field: port: // ./in.cue:142:50 } } p5: (struct){ #X: (_|_){ // [incomplete] medium.p5.#X.port: cyclic reference to field port: // ./in.cue:150:4 } #Y: (_|_){ // [incomplete] medium.p5.#Y: undefined field: port: // ./in.cue:158:50 } Y: (struct){ } } p6: (struct){ #X: (_|_){ // [incomplete] medium.p6.#X.port: cyclic reference to field port: // ./in.cue:172:4 } Y: (struct){ } #Y: (_|_){ // [incomplete] medium.p6.#Y: undefined field: port: // ./in.cue:186:50 } } } large: (struct){ #userHostPort: (string){ "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\\d+))?$" } p1: (struct){ Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } X: (_|_){ // [incomplete] large.p1.X: undefined field: port: // ./in.cue:199:33 } #X: (_|_){ // [incomplete] large.p1.#X.port: cyclic reference to field port: // ./in.cue:211:4 userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (_|_){ // [incomplete] large.p1.X: undefined field: port: // ./in.cue:199:33 } } p2: (struct){ X: (_|_){ // [incomplete] large.p2.X: undefined field: port: // ./in.cue:235:33 } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #X: (_|_){ // [incomplete] large.p2.#X.port: cyclic reference to field port: // ./in.cue:252:4 userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (_|_){ // [incomplete] large.p2.#Y: error in call to regexp.FindNamedSubmatch: non-concrete value _: // ./in.cue:272:7 } } p3: (struct){ X: (_|_){ // [incomplete] large.p3.X: undefined field: port: // ./in.cue:276:33 } #X: (_|_){ // [incomplete] large.p3.#X.port: cyclic reference to field port: // ./in.cue:288:4 userinfo: (string){ "user@" } host: (string){ "mod.test" } } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } #Y: (_|_){ // [incomplete] large.p3.#Y: error in call to regexp.FindNamedSubmatch: non-concrete value _: // ./in.cue:313:7 } } p4: (struct){ X: (_|_){ // [incomplete] large.p4.X: undefined field: port: // ./in.cue:317:33 } #X: (_|_){ // [incomplete] large.p4.#X.port: cyclic reference to field port: // ./in.cue:329:4 userinfo: (string){ "user@" } host: (string){ "mod.test" } } #Y: (_|_){ // [incomplete] large.p4.#Y: error in call to regexp.FindNamedSubmatch: non-concrete value _: // ./in.cue:337:7 } Y: (struct){ userinfo: (string){ "user" } host: (string){ "mod.test" } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,35 +1,34 @@ (struct){ minimal: (struct){ a: (_|_){ - // [cycle] minimal.b: cycle with field a.port: - // ./in.cue:18:6 + // [incomplete] minimal.a.port: cyclic reference to field port: + // ./in.cue:12:3 } b: (_|_){ - // [cycle] minimal.b: cycle with field a.port: - // ./in.cue:18:6 + // [incomplete] minimal.b.port: cyclic reference to field port: + // ./in.cue:18:3 } } small: (struct){ #userHostPort: (string){ "^(:(?P\\d+))?$" } p1: (struct){ - #Y: (#struct){ - port: (string){ "" } - } - #X: (_|_){ - // [cycle] small.p1.#X: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: - // ./in.cue:31:7 - // small.p1.#X: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: - // ./in.cue:34:7 - } - } - p2: (struct){ - #X: (_|_){ - // [cycle] small.p2.#Y: cycle with field #X.port: - // ./in.cue:50:47 - } - #Y: (_|_){ - // [cycle] small.p2.#Y: cycle with field #X.port: - // ./in.cue:50:47 + #Y: (_|_){ + // [incomplete] small.p1.#Y: undefined field: port: + // ./in.cue:28:50 + } + #X: (_|_){ + // [incomplete] small.p1.#X.port: cyclic reference to field port: + // ./in.cue:31:4 + } + } + p2: (struct){ + #X: (_|_){ + // [incomplete] small.p2.#X.port: cyclic reference to field port: + // ./in.cue:42:4 + } + #Y: (_|_){ + // [incomplete] small.p2.#Y: undefined field: port: + // ./in.cue:50:50 } } } @@ -36,65 +35,61 @@ medium: (struct){ #userHostPort: (string){ "^(:(?P\\d+))?$" } p1: (struct){ - #Y: (#struct){ - port: (string){ "" } - } - Y: (_|_){ - // [cycle] medium.p1.Y: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: - // ./in.cue:61:7 - } - #X: (#struct){ - port: (string){ "" } - } - } - p2: (struct){ - #Y: (#struct){ - port: (string){ "" } - } - #X: (#struct){ - port: (string){ "" } - } - Y: (_|_){ - // [cycle] medium.p2.Y: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: - // ./in.cue:95:7 - } - } - p3: (struct){ - Y: (_|_){ - // [cycle] medium.p3.#X: cycle with field Y.port: - // ./in.cue:114:7 + #Y: (_|_){ + // [incomplete] medium.p1.#Y: undefined field: port: + // ./in.cue:58:50 + } + Y: (struct){ + } + #X: (_|_){ + // [incomplete] medium.p1.#X.port: cyclic reference to field port: + // ./in.cue:70:4 + } + } + p2: (struct){ + #Y: (_|_){ + // [incomplete] medium.p2.#Y: undefined field: port: + // ./in.cue:80:50 + } + #X: (_|_){ + // [incomplete] medium.p2.#X.port: cyclic reference to field port: + // ./in.cue:86:4 + } + Y: (struct){ + } + } + p3: (struct){ + Y: (struct){ } #Y: (_|_){ // [incomplete] medium.p3.#Y: undefined field: port: - // ./in.cue:108:47 - } - #X: (_|_){ - // [cycle] medium.p3.#X: cycle with field Y.port: - // ./in.cue:114:7 - } - } - p4: (struct){ - Y: (_|_){ - // [cycle] medium.p4.#X: cycle with field Y.port: - // ./in.cue:134:7 - } - #X: (_|_){ - // [cycle] medium.p4.#X: cycle with field Y.port: - // ./in.cue:134:7 - } - #Y: (_|_){ - // [cycle] medium.p4.#X: cycle with field Y.port: - // ./in.cue:134:7 + // ./in.cue:108:50 + } + #X: (_|_){ + // [incomplete] medium.p3.#X.port: cyclic reference to field port: + // ./in.cue:114:4 + } + } + p4: (struct){ + Y: (struct){ + } + #X: (_|_){ + // [incomplete] medium.p4.#X.port: cyclic reference to field port: + // ./in.cue:134:4 + } + #Y: (_|_){ + // [incomplete] medium.p4.#Y: undefined field: port: + // ./in.cue:142:50 } } p5: (struct){ #X: (_|_){ - // [cycle] medium.p5.#Y: cycle with field #X.port: - // ./in.cue:158:47 - } - #Y: (_|_){ - // [cycle] medium.p5.#Y: cycle with field #X.port: - // ./in.cue:158:47 + // [incomplete] medium.p5.#X.port: cyclic reference to field port: + // ./in.cue:150:4 + } + #Y: (_|_){ + // [incomplete] medium.p5.#Y: undefined field: port: + // ./in.cue:158:50 } Y: (struct){ } @@ -101,14 +96,14 @@ } p6: (struct){ #X: (_|_){ - // [cycle] medium.p6.#Y: cycle with field #X.port: - // ./in.cue:186:47 - } - Y: (struct){ - } - #Y: (_|_){ - // [cycle] medium.p6.#Y: cycle with field #X.port: - // ./in.cue:186:47 + // [incomplete] medium.p6.#X.port: cyclic reference to field port: + // ./in.cue:172:4 + } + Y: (struct){ + } + #Y: (_|_){ + // [incomplete] medium.p6.#Y: undefined field: port: + // ./in.cue:186:50 } } } @@ -115,81 +110,83 @@ large: (struct){ #userHostPort: (string){ "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\\d+))?$" } p1: (struct){ - Y: (_|_){ - // [cycle] large.p1.Y: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: - // ./in.cue:226:7 - } - X: (string){ "user@mod.test" } - #X: (_|_){ - // [cycle] large.p1.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:202:7 - // large.p1.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:205:7 - } - #Y: (#struct){ - host: (string){ "mod.test" } - port: (string){ "" } - userinfo: (string){ "user" } - } - } - p2: (struct){ - X: (string){ "user@mod.test" } - Y: (_|_){ - // [cycle] large.p2.Y: cycle error referencing port: - // ./in.cue:267:10 - } - #X: (_|_){ - // [cycle] large.p2.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:243:7 - // large.p2.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:246:7 - // large.p2.Y: cycle error referencing port: - // ./in.cue:267:10 - } - #Y: (#struct){ - host: (string){ "mod.test" } - port: (string){ "" } - userinfo: (string){ "user" } - } - } - p3: (struct){ - X: (string){ "user@mod.test" } - #X: (_|_){ - // [cycle] large.p3.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:279:7 - // large.p3.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:282:7 - // large.p3.Y: cycle error referencing port: - // ./in.cue:308:10 - } - Y: (_|_){ - // [cycle] large.p3.Y: cycle error referencing port: - // ./in.cue:308:10 - } - #Y: (#struct){ - host: (string){ "mod.test" } - port: (string){ "" } - userinfo: (string){ "user" } - } - } - p4: (struct){ - X: (string){ "user@mod.test" } - #X: (_|_){ - // [cycle] large.p4.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:320:7 - // large.p4.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: - // ./in.cue:323:7 - // large.p4.Y: cycle error referencing port: - // ./in.cue:351:10 - } - #Y: (#struct){ - host: (string){ "mod.test" } - port: (string){ "" } - userinfo: (string){ "user" } - } - Y: (_|_){ - // [cycle] large.p4.Y: cycle error referencing port: - // ./in.cue:351:10 + Y: (struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + X: (_|_){ + // [incomplete] large.p1.X: undefined field: port: + // ./in.cue:199:33 + } + #X: (_|_){ + // [incomplete] large.p1.#X.port: cyclic reference to field port: + // ./in.cue:211:4 + userinfo: (string){ "user@" } + host: (string){ "mod.test" } + } + #Y: (_|_){ + // [incomplete] large.p1.X: undefined field: port: + // ./in.cue:199:33 + } + } + p2: (struct){ + X: (_|_){ + // [incomplete] large.p2.X: undefined field: port: + // ./in.cue:235:33 + } + Y: (struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + #X: (_|_){ + // [incomplete] large.p2.#X.port: cyclic reference to field port: + // ./in.cue:252:4 + userinfo: (string){ "user@" } + host: (string){ "mod.test" } + } + #Y: (_|_){ + // [incomplete] large.p2.#Y: error in call to regexp.FindNamedSubmatch: non-concrete value _: + // ./in.cue:272:7 + } + } + p3: (struct){ + X: (_|_){ + // [incomplete] large.p3.X: undefined field: port: + // ./in.cue:276:33 + } + #X: (_|_){ + // [incomplete] large.p3.#X.port: cyclic reference to field port: + // ./in.cue:288:4 + userinfo: (string){ "user@" } + host: (string){ "mod.test" } + } + Y: (struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } + } + #Y: (_|_){ + // [incomplete] large.p3.#Y: error in call to regexp.FindNamedSubmatch: non-concrete value _: + // ./in.cue:313:7 + } + } + p4: (struct){ + X: (_|_){ + // [incomplete] large.p4.X: undefined field: port: + // ./in.cue:317:33 + } + #X: (_|_){ + // [incomplete] large.p4.#X.port: cyclic reference to field port: + // ./in.cue:329:4 + userinfo: (string){ "user@" } + host: (string){ "mod.test" } + } + #Y: (_|_){ + // [incomplete] large.p4.#Y: error in call to regexp.FindNamedSubmatch: non-concrete value _: + // ./in.cue:337:7 + } + Y: (struct){ + userinfo: (string){ "user" } + host: (string){ "mod.test" } } } } -- diff/todo/p2 -- error message: no mention of cycle path -- out/eval -- (struct){ minimal: (struct){ a: (_|_){ // [cycle] minimal.b: cycle with field a.port: // ./in.cue:18:6 } b: (_|_){ // [cycle] minimal.b: cycle with field a.port: // ./in.cue:18:6 } } small: (struct){ #userHostPort: (string){ "^(:(?P\\d+))?$" } p1: (struct){ #Y: (#struct){ port: (string){ "" } } #X: (_|_){ // [cycle] small.p1.#X: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: // ./in.cue:31:7 // small.p1.#X: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: // ./in.cue:34:7 } } p2: (struct){ #X: (_|_){ // [cycle] small.p2.#Y: cycle with field #X.port: // ./in.cue:50:47 } #Y: (_|_){ // [cycle] small.p2.#Y: cycle with field #X.port: // ./in.cue:50:47 } } } medium: (struct){ #userHostPort: (string){ "^(:(?P\\d+))?$" } p1: (struct){ #Y: (#struct){ port: (string){ "" } } Y: (_|_){ // [cycle] medium.p1.Y: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: // ./in.cue:61:7 } #X: (#struct){ port: (string){ "" } } } p2: (struct){ #Y: (#struct){ port: (string){ "" } } #X: (#struct){ port: (string){ "" } } Y: (_|_){ // [cycle] medium.p2.Y: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: // ./in.cue:95:7 } } p3: (struct){ Y: (_|_){ // [cycle] medium.p3.#X: cycle with field Y.port: // ./in.cue:114:7 } #Y: (_|_){ // [incomplete] medium.p3.#Y: undefined field: port: // ./in.cue:108:47 } #X: (_|_){ // [cycle] medium.p3.#X: cycle with field Y.port: // ./in.cue:114:7 } } p4: (struct){ Y: (_|_){ // [cycle] medium.p4.#X: cycle with field Y.port: // ./in.cue:134:7 } #X: (_|_){ // [cycle] medium.p4.#X: cycle with field Y.port: // ./in.cue:134:7 } #Y: (_|_){ // [cycle] medium.p4.#X: cycle with field Y.port: // ./in.cue:134:7 } } p5: (struct){ #X: (_|_){ // [cycle] medium.p5.#Y: cycle with field #X.port: // ./in.cue:158:47 } #Y: (_|_){ // [cycle] medium.p5.#Y: cycle with field #X.port: // ./in.cue:158:47 } Y: (struct){ } } p6: (struct){ #X: (_|_){ // [cycle] medium.p6.#Y: cycle with field #X.port: // ./in.cue:186:47 } Y: (struct){ } #Y: (_|_){ // [cycle] medium.p6.#Y: cycle with field #X.port: // ./in.cue:186:47 } } } large: (struct){ #userHostPort: (string){ "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\\d+))?$" } p1: (struct){ Y: (_|_){ // [cycle] large.p1.Y: circular dependency in evaluation of conditionals: #Y.port changed after evaluation: // ./in.cue:226:7 } X: (string){ "user@mod.test" } #X: (_|_){ // [cycle] large.p1.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:202:7 // large.p1.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:205:7 } #Y: (#struct){ host: (string){ "mod.test" } port: (string){ "" } userinfo: (string){ "user" } } } p2: (struct){ X: (string){ "user@mod.test" } Y: (_|_){ // [cycle] large.p2.Y: cycle error referencing port: // ./in.cue:267:10 } #X: (_|_){ // [cycle] large.p2.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:243:7 // large.p2.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:246:7 // large.p2.Y: cycle error referencing port: // ./in.cue:267:10 } #Y: (#struct){ host: (string){ "mod.test" } port: (string){ "" } userinfo: (string){ "user" } } } p3: (struct){ X: (string){ "user@mod.test" } #X: (_|_){ // [cycle] large.p3.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:279:7 // large.p3.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:282:7 // large.p3.Y: cycle error referencing port: // ./in.cue:308:10 } Y: (_|_){ // [cycle] large.p3.Y: cycle error referencing port: // ./in.cue:308:10 } #Y: (#struct){ host: (string){ "mod.test" } port: (string){ "" } userinfo: (string){ "user" } } } p4: (struct){ X: (string){ "user@mod.test" } #X: (_|_){ // [cycle] large.p4.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:320:7 // large.p4.#X: circular dependency in evaluation of conditionals: Y.userinfo changed after evaluation: // ./in.cue:323:7 // large.p4.Y: cycle error referencing port: // ./in.cue:351:10 } #Y: (#struct){ host: (string){ "mod.test" } port: (string){ "" } userinfo: (string){ "user" } } Y: (_|_){ // [cycle] large.p4.Y: cycle error referencing port: // ./in.cue:351:10 } } } } -- out/compile -- --- in.cue { minimal: { a: { if (〈1;b〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } } b: { if (〈1;a〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } } } small: { #userHostPort: "^(:(?P\\d+))?$" p1: { #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) #X: { if (〈1;#Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;#Y〉.port, 10)) } } } p2: { #X: { if (〈1;#Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;#Y〉.port, 10)) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) } } medium: { #userHostPort: "^(:(?P\\d+))?$" p1: { #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) Y: { if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #X: { if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } } p2: { #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) #X: { if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } Y: { if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } } p3: { Y: { if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) #X: { if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } } p4: { Y: { if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #X: { if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) } p5: { #X: { if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) Y: { if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } } p6: { #X: { if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } Y: { if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port) } } large: { #userHostPort: "^((?P[[:alnum:]]*)@)?(?P[[:alnum:].]+)(:(?P\\d+))?$" p1: { Y: { userinfo: "user" host: "mod.test" } X: ((〈0;#X〉.userinfo + 〈0;#X〉.host) + 〈0;#X〉.port) #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) } p2: { X: ((〈0;#X〉.userinfo + 〈0;#X〉.host) + 〈0;#X〉.port) Y: { userinfo: "user" host: "mod.test" } #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) } p3: { X: ((〈0;#X〉.userinfo + 〈0;#X〉.host) + 〈0;#X〉.port) #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } Y: { userinfo: "user" host: "mod.test" } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) } p4: { X: ((〈0;#X〉.userinfo + 〈0;#X〉.host) + 〈0;#X〉.port) #X: { if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) { userinfo: "" } if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: (〈2;Y〉.userinfo + "@") } host: 〈1;Y〉.host if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) { port: "" } if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: (":" + 〈import;strconv〉.FormatInt(〈2;Y〉.port, 10)) } } #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉) Y: { userinfo: "user" host: "mod.test" } Y: { if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) { userinfo: 〈2;#Y〉.userinfo } host: 〈1;#Y〉.host if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) { port: 〈import;strconv〉.Atoi(〈2;#Y〉.port) } } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/comprehension.txtar000066400000000000000000001037571474664451600241360ustar00rootroot00000000000000-- in.cue -- // Allow lookup in partially evaluated struct as long as the end result is // concrete. A: { a: { parent: "" children: [for k, v in A if v.parent == k {k}] } b: { parent: "a" children: [for k, v in A if v.parent == k {k}] } } // This should result in an incomplete error (a reference cycle error classifies // as incomplete). B: { a: { parent: "" children: [for k, v in B for _, w in v.children {k}] } } // Issue #486 Issue486: { A: { a: { parent: "" children: [...string] } b: { parent: "a" children: [...string] } c: { parent: "b" children: [...string] } } A: [Name=string]: { children: [ for k, v in A if v.parent == Name { k }, ] } } // Issue #1666 issue1666: { #E: { f1: [string]: #E | [...#E] f2: [string]: t: #E } _e: #E _e: f2: a: _ e: _e & { f1: { for fk, s in _e.f2 { (fk): s.t } } } } // Issue #779: bidirectional projection // Should be allowed as long as the set of fields is not modified as a result // of a comprehension. issue779: { X: Y.message STATE: { for k, v in Y { if k != "message" { "\(k)": v } } } Y: STATE & { message: X } X: "test" STATE: { code: 101 } } // Comprehension ends up inserting in the same arcs over which it // is iterating. This is fine as long as the set is not altered. // Issue #1934 selfReferential: T1: { S: d: "bar" T: e: S: a: "foo" for s, v in S for t, _ in T { T: (t): S: (s): v } } // selfReferential comprehenion for list. // Issue #1934 selfReferential: list: { panels: [ for i, _ in panels { id: i } ] panels: [{}, {}, {}] } selfReferential: insertionError: { A: { foo: 1 for x in A { // May not insert foo3. Use dynamic references to force the // comprehension to be evaluated in the struct in which it is // defined. ("foo3"): 1 } } } // A comprehension should not recursively evaluated arcs, so that a // structural cycle can be avoided when unnecessary. selfReferential: acrossOr: t1: p1: { o: #Output & { retry: reject: "ok" } #AllOutputs: { reject: string resource: string retry: #Output } #Output: or([for name, config in #AllOutputs { (name): config }]) } selfReferential: acrossOr: t1: p2: { #Output: or([for name, config in #AllOutputs { (name): config }]) o: #Output & { retry: reject: "ok" } #AllOutputs: { reject: string resource: string retry: #Output } } selfReferential: acrossOr: t1: p3: { #Output: or([for name, config in #AllOutputs { (name): config }]) #AllOutputs: { reject: string resource: string retry: #Output } o: #Output & { retry: reject: "ok" } } selfReferential: acrossOr: t2: p1: { d: or([for x, y in #A { y }]) o: d & { b: 2 } #A: { d1: int d2: string d3: b: d } } selfReferential: acrossOr: t2: p2: { o: d & { b: 2 } d: or([for x, y in #A { y }]) #A: { d1: int d2: string d3: b: d } } selfReferential: acrossOr: t2: p3: { o: d & { b: 2 } #A: { d1: int d2: string d3: b: d } d: or([for x, y in #A { y }]) } issue1881: p1: { o: #Output & { retry: output: reject: "ok" } #AllOutputs: { reject: string resource: string retry: output: #Output } #Output: or([for name, config in #AllOutputs { (name): config }]) } issue1881: p2: { #AllOutputs: { reject: string resource: string retry: output: #Output } o: #Output & { retry: output: reject: "ok" } #Output: or([for name, config in #AllOutputs { (name): config }]) } issue1881: p3: { #AllOutputs: { reject: string resource: string retry: output: #Output } #Output: or([for name, config in #AllOutputs { (name): config }]) o: #Output & { retry: output: reject: "ok" } } siblingInsertion: t1: p1: { D: "logging": _ deployment: _ for k, v in deployment for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } for id, v in D { deployment: (id): env2: ENV: "True" } } siblingInsertion: t1: p2: { D: "logging": _ deployment: _ for id, v in D { deployment: (id): env2: ENV: "True" } for k, v in deployment for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } } siblingInsertion: t2: p1: { D: "logging": _ deployment: _ for k, v in deployment { for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } } for id, v in D { deployment: (id): env2: ENV: "True" } } siblingInsertion: t2: p2: { D: "logging": _ deployment: _ for k, v in deployment { for k1, v2 in v.env2 { deployment: (k): env: (k1): v2 } } for id, v in D { deployment: (id): env2: ENV: "True" } } // Issue #1407 // Ensure there is a useful error message. selfReferential: fail: { a: {} b: a.x != "" if b { } } // avoid infinite recursion issue2367: { a: _ for x in [a] {a: x} } -- out/evalalpha/stats -- Leaks: 777 Freed: 68 Reused: 68 Allocs: 777 Retain: 0 Unifications: 502 Conjuncts: 3097 Disjuncts: 196 -- out/evalalpha -- Errors: selfReferential.insertionError.A: adding field foo3 not allowed as field set was already referenced: ./in.cue:117:14 Result: (_|_){ // [eval] A: (struct){ a: (struct){ parent: (string){ "" } children: (#list){ } } b: (struct){ parent: (string){ "a" } children: (#list){ } } } B: (struct){ a: (struct){ parent: (string){ "" } children: (_|_){ // [incomplete] B.a.children: cannot range over v.children (incomplete type list): // ./in.cue:19:40 } } } Issue486: (struct){ A: (struct){ a: (struct){ parent: (string){ "" } children: (#list){ 0: (string){ "b" } } } b: (struct){ parent: (string){ "a" } children: (#list){ 0: (string){ "c" } } } c: (struct){ parent: (string){ "b" } children: (#list){ } } } } issue1666: (struct){ #E: (#struct){ f1: (#struct){ } f2: (#struct){ } } _e: (#struct){ f2: (#struct){ a: (#struct){ t: ~(issue1666.#E) } } f1: (#struct){ } } e: (#struct){ f1: (#struct){ a: (#struct){ f1: (#struct){ } f2: (#struct){ } } } f2: (#struct){ a: (#struct){ t: ~(issue1666.#E) } } } } issue779: (struct){ X: (string){ "test" } STATE: (struct){ code: (int){ 101 } } Y: (struct){ message: (string){ "test" } code: (int){ 101 } } } selfReferential: (_|_){ // [eval] T1: (struct){ S: (struct){ d: (string){ "bar" } } T: (struct){ e: (struct){ S: (struct){ a: (string){ "foo" } d: (string){ "bar" } } } } } list: (struct){ panels: (#list){ 0: (struct){ id: (int){ 0 } } 1: (struct){ id: (int){ 1 } } 2: (struct){ id: (int){ 2 } } } } insertionError: (_|_){ // [eval] A: (_|_){ // [eval] selfReferential.insertionError.A: adding field foo3 not allowed as field set was already referenced: // ./in.cue:117:14 foo: (int){ 1 } } } acrossOr: (struct){ t1: (struct){ p1: (struct){ o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p2: (struct){ #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } p3: (struct){ #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } } } t2: (struct){ p1: (struct){ d: ((int|string)){ |((int){ int }, (string){ string }) } o: (struct){ b: (int){ 2 } } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } } p2: (struct){ o: (struct){ b: (int){ 2 } } d: ((int|string)){ |((int){ int }, (string){ string }) } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } } p3: (struct){ o: (struct){ b: (int){ 2 } } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } d: ((int|string)){ |((int){ int }, (string){ string }) } } } } fail: (_|_){ // [incomplete] selfReferential.fail.b: undefined field: x: // ./in.cue:300:7 a: (struct){ } b: (_|_){ // [incomplete] selfReferential.fail.b: undefined field: x: // ./in.cue:300:7 } } } issue1881: (struct){ p1: (struct){ o: (#struct){ retry: (struct){ output: (#struct){ reject: (string){ "ok" } } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p2: (struct){ #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } o: (#struct){ retry: (struct){ output: (#struct){ reject: (string){ "ok" } } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p3: (struct){ #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } o: (#struct){ retry: (struct){ output: (#struct){ reject: (string){ "ok" } } } } } } siblingInsertion: (struct){ t1: (struct){ p1: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } p2: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } } t2: (struct){ p1: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } p2: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } } } issue2367: (struct){ a: (_){ _ } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,5 +1,6 @@ Errors: -selfReferential.insertionError.A: field foo3 not allowed by earlier comprehension or reference cycle +selfReferential.insertionError.A: adding field foo3 not allowed as field set was already referenced: + ./in.cue:117:14 Result: (_|_){ @@ -19,7 +20,9 @@ B: (struct){ a: (struct){ parent: (string){ "" } - children: (#list){ + children: (_|_){ + // [incomplete] B.a.children: cannot range over v.children (incomplete type list): + // ./in.cue:19:40 } } } @@ -52,17 +55,12 @@ } } _e: (#struct){ - f1: (#struct){ - } - f2: (#struct){ - a: (#struct){ - t: (#struct){ - f1: (#struct){ - } - f2: (#struct){ - } - } - } + f2: (#struct){ + a: (#struct){ + t: ~(issue1666.#E) + } + } + f1: (#struct){ } } e: (#struct){ @@ -76,12 +74,7 @@ } f2: (#struct){ a: (#struct){ - t: (#struct){ - f1: (#struct){ - } - f2: (#struct){ - } - } + t: ~(issue1666.#E) } } } @@ -127,9 +120,9 @@ insertionError: (_|_){ // [eval] A: (_|_){ - // [eval] selfReferential.insertionError.A: field foo3 not allowed by earlier comprehension or reference cycle + // [eval] selfReferential.insertionError.A: adding field foo3 not allowed as field set was already referenced: + // ./in.cue:117:14 foo: (int){ 1 } - foo3: (int){ 1 } } } acrossOr: (struct){ @@ -254,7 +247,7 @@ issue1881: (struct){ p1: (struct){ o: (#struct){ - retry: (#struct){ + retry: (struct){ output: (#struct){ reject: (string){ "ok" } } @@ -290,7 +283,7 @@ } } o: (#struct){ - retry: (#struct){ + retry: (struct){ output: (#struct){ reject: (string){ "ok" } } @@ -320,7 +313,7 @@ resource: (string){ string } }) } o: (#struct){ - retry: (#struct){ + retry: (struct){ output: (#struct){ reject: (string){ "ok" } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 50 -Freed: 1270 -Reused: 1260 -Allocs: 60 -Retain: 145 +Leaks: 777 +Freed: 68 +Reused: 68 +Allocs: 777 +Retain: 0 -Unifications: 832 -Conjuncts: 2525 -Disjuncts: 1404 +Unifications: 502 +Conjuncts: 3097 +Disjuncts: 196 -- out/eval/stats -- Leaks: 50 Freed: 1270 Reused: 1260 Allocs: 60 Retain: 145 Unifications: 832 Conjuncts: 2525 Disjuncts: 1404 -- diff/explanation -- B.a.children: now correctly marked as incomplete -- out/eval -- Errors: selfReferential.insertionError.A: field foo3 not allowed by earlier comprehension or reference cycle Result: (_|_){ // [eval] A: (struct){ a: (struct){ parent: (string){ "" } children: (#list){ } } b: (struct){ parent: (string){ "a" } children: (#list){ } } } B: (struct){ a: (struct){ parent: (string){ "" } children: (#list){ } } } Issue486: (struct){ A: (struct){ a: (struct){ parent: (string){ "" } children: (#list){ 0: (string){ "b" } } } b: (struct){ parent: (string){ "a" } children: (#list){ 0: (string){ "c" } } } c: (struct){ parent: (string){ "b" } children: (#list){ } } } } issue1666: (struct){ #E: (#struct){ f1: (#struct){ } f2: (#struct){ } } _e: (#struct){ f1: (#struct){ } f2: (#struct){ a: (#struct){ t: (#struct){ f1: (#struct){ } f2: (#struct){ } } } } } e: (#struct){ f1: (#struct){ a: (#struct){ f1: (#struct){ } f2: (#struct){ } } } f2: (#struct){ a: (#struct){ t: (#struct){ f1: (#struct){ } f2: (#struct){ } } } } } } issue779: (struct){ X: (string){ "test" } STATE: (struct){ code: (int){ 101 } } Y: (struct){ message: (string){ "test" } code: (int){ 101 } } } selfReferential: (_|_){ // [eval] T1: (struct){ S: (struct){ d: (string){ "bar" } } T: (struct){ e: (struct){ S: (struct){ a: (string){ "foo" } d: (string){ "bar" } } } } } list: (struct){ panels: (#list){ 0: (struct){ id: (int){ 0 } } 1: (struct){ id: (int){ 1 } } 2: (struct){ id: (int){ 2 } } } } insertionError: (_|_){ // [eval] A: (_|_){ // [eval] selfReferential.insertionError.A: field foo3 not allowed by earlier comprehension or reference cycle foo: (int){ 1 } foo3: (int){ 1 } } } acrossOr: (struct){ t1: (struct){ p1: (struct){ o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p2: (struct){ #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } p3: (struct){ #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } o: (#struct){ retry: (#struct){ reject: (string){ "ok" } } } } } t2: (struct){ p1: (struct){ d: ((int|string)){ |((int){ int }, (string){ string }) } o: (struct){ b: (int){ 2 } } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } } p2: (struct){ o: (struct){ b: (int){ 2 } } d: ((int|string)){ |((int){ int }, (string){ string }) } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } } p3: (struct){ o: (struct){ b: (int){ 2 } } #A: (#struct){ d1: (int){ int } d2: (string){ string } d3: (#struct){ b: ((int|string)){ |((int){ int }, (string){ string }) } } } d: ((int|string)){ |((int){ int }, (string){ string }) } } } } fail: (_|_){ // [incomplete] selfReferential.fail.b: undefined field: x: // ./in.cue:300:7 a: (struct){ } b: (_|_){ // [incomplete] selfReferential.fail.b: undefined field: x: // ./in.cue:300:7 } } } issue1881: (struct){ p1: (struct){ o: (#struct){ retry: (#struct){ output: (#struct){ reject: (string){ "ok" } } } } #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p2: (struct){ #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } o: (#struct){ retry: (#struct){ output: (#struct){ reject: (string){ "ok" } } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } p3: (struct){ #AllOutputs: (#struct){ reject: (string){ string } resource: (string){ string } retry: (#struct){ output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } } } #Output: (#struct){ |((#struct){ reject: (string){ string } }, (#struct){ resource: (string){ string } }) } o: (#struct){ retry: (#struct){ output: (#struct){ reject: (string){ "ok" } } } } } } siblingInsertion: (struct){ t1: (struct){ p1: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } p2: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } } t2: (struct){ p1: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } p2: (struct){ D: (struct){ logging: (_){ _ } } deployment: (struct){ logging: (struct){ env2: (struct){ ENV: (string){ "True" } } env: (struct){ ENV: (string){ "True" } } } } } } } issue2367: (struct){ a: (_){ _ } } } -- out/compile -- --- in.cue { A: { a: { parent: "" children: [ for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { 〈1;k〉 }, ] } b: { parent: "a" children: [ for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈0;k〉) { 〈1;k〉 }, ] } } B: { a: { parent: "" children: [ for k, v in 〈3;B〉 for _, w in 〈0;v〉.children { 〈2;k〉 }, ] } } Issue486: { A: { a: { parent: "" children: [ ...string, ] } b: { parent: "a" children: [ ...string, ] } c: { parent: "b" children: [ ...string, ] } } A: { [string]: { children: [ for k, v in 〈3;A〉 if (〈0;v〉.parent == 〈3;-〉) { 〈1;k〉 }, ] } } } issue1666: { #E: { f1: { [string]: (〈2;#E〉|[ ...〈3;#E〉, ]) } f2: { [string]: { t: 〈3;#E〉 } } } _e: 〈0;#E〉 _e: { f2: { a: _ } } e: (〈0;_e〉 & { f1: { for fk, s in 〈2;_e〉.f2 { 〈1;fk〉: 〈1;s〉.t } } }) } issue779: { X: 〈0;Y〉.message STATE: { for k, v in 〈1;Y〉 { if (〈1;k〉 != "message") { "\(〈2;k〉)": 〈2;v〉 } } } Y: (〈0;STATE〉 & { message: 〈1;X〉 }) X: "test" STATE: { code: 101 } } selfReferential: { T1: { S: { d: "bar" } T: { e: { S: { a: "foo" } } } for s, v in 〈0;S〉 for t, _ in 〈1;T〉 { T: { 〈2;t〉: { S: { 〈5;s〉: 〈5;v〉 } } } } } } selfReferential: { list: { panels: [ for i, _ in 〈1;panels〉 { id: 〈1;i〉 }, ] panels: [ {}, {}, {}, ] } } selfReferential: { insertionError: { A: { foo: 1 for _, x in 〈1;A〉 { "foo3": 1 } } } } selfReferential: { acrossOr: { t1: { p1: { o: (〈0;#Output〉 & { retry: { reject: "ok" } }) #AllOutputs: { reject: string resource: string retry: 〈1;#Output〉 } #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) } } } } selfReferential: { acrossOr: { t1: { p2: { #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) o: (〈0;#Output〉 & { retry: { reject: "ok" } }) #AllOutputs: { reject: string resource: string retry: 〈1;#Output〉 } } } } } selfReferential: { acrossOr: { t1: { p3: { #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) #AllOutputs: { reject: string resource: string retry: 〈1;#Output〉 } o: (〈0;#Output〉 & { retry: { reject: "ok" } }) } } } } selfReferential: { acrossOr: { t2: { p1: { d: or([ for x, y in 〈1;#A〉 { 〈1;y〉 }, ]) o: (〈0;d〉 & { b: 2 }) #A: { d1: int d2: string d3: { b: 〈2;d〉 } } } } } } selfReferential: { acrossOr: { t2: { p2: { o: (〈0;d〉 & { b: 2 }) d: or([ for x, y in 〈1;#A〉 { 〈1;y〉 }, ]) #A: { d1: int d2: string d3: { b: 〈2;d〉 } } } } } } selfReferential: { acrossOr: { t2: { p3: { o: (〈0;d〉 & { b: 2 }) #A: { d1: int d2: string d3: { b: 〈2;d〉 } } d: or([ for x, y in 〈1;#A〉 { 〈1;y〉 }, ]) } } } } issue1881: { p1: { o: (〈0;#Output〉 & { retry: { output: { reject: "ok" } } }) #AllOutputs: { reject: string resource: string retry: { output: 〈2;#Output〉 } } #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) } } issue1881: { p2: { #AllOutputs: { reject: string resource: string retry: { output: 〈2;#Output〉 } } o: (〈0;#Output〉 & { retry: { output: { reject: "ok" } } }) #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) } } issue1881: { p3: { #AllOutputs: { reject: string resource: string retry: { output: 〈2;#Output〉 } } #Output: or([ for name, config in 〈1;#AllOutputs〉 { 〈1;name〉: 〈1;config〉 }, ]) o: (〈0;#Output〉 & { retry: { output: { reject: "ok" } } }) } } siblingInsertion: { t1: { p1: { D: { logging: _ } deployment: _ for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { deployment: { 〈3;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } } } } siblingInsertion: { t1: { p2: { D: { logging: _ } deployment: _ for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } for k, v in 〈0;deployment〉 for k1, v2 in 〈0;v〉.env2 { deployment: { 〈3;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } } } } siblingInsertion: { t2: { p1: { D: { logging: _ } deployment: _ for k, v in 〈0;deployment〉 { for k1, v2 in 〈1;v〉.env2 { deployment: { 〈4;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } } for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } } } } siblingInsertion: { t2: { p2: { D: { logging: _ } deployment: _ for k, v in 〈0;deployment〉 { for k1, v2 in 〈1;v〉.env2 { deployment: { 〈4;k〉: { env: { 〈4;k1〉: 〈4;v2〉 } } } } } for id, v in 〈0;D〉 { deployment: { 〈2;id〉: { env2: { ENV: "True" } } } } } } } selfReferential: { fail: { a: {} b: (〈0;a〉.x != "") if 〈0;b〉 {} } } issue2367: { a: _ for _, x in [ 〈1;a〉, ] { a: 〈1;x〉 } } } cue-lang-cue-db9cc73/cue/testdata/cycle/constraints.txtar000066400000000000000000001002701474664451600236170ustar00rootroot00000000000000-- in.cue -- // Not a cycle: the structure in x (c) only triggers one further // instantiation of y, but not enough to trigger another round. safeCycle: simple2: { y: [string]: b: c: y x: y x: c: y } // Not a cycle: the structure in x (c) only triggers one further // instantiation of y, but not enough to trigger another round. safeCycle: long1: { y: [string]: b: y x: y x: c: b: e: b: c: _ } // Not a cycle: the structure in x (c) only triggers one further // instantiation of y, but not enough to trigger another round. safeCycle: long2: { a: [string]: b: a x: a x: c: b: c: b: c: {} } // noCyclePattern is similar to the above cases, but involving more patterns // and various lengths. noCyclePattern: _ noCyclePattern: t1: { #D: [string]: #D a: {} [string]: #D [string]: b: c: {} } noCyclePattern: t2: { #D: [string]: x: #D a: {} [string]: #D [string]: b: x: c: {} } noCyclePattern: t3: { _D: [string]: _T _T: x: _D [string]: _D [string]: b: x: c: {} a: {} } noCyclePattern: t4: { _D: [string]: x: _T _T: y: _D [string]: _D [string]: b: x: {} a: {} } noCyclePattern: t5: { _D: [string]: x: _T _T: y: _D [string]: _D [string]: b: x: y: c: x: {} a: {} } // This example also has an embedding, in which case it should still behave // the same. noCyclePattern: t6: { #D: [string]: #E #E: t: #T #T: { { object: #S } } #S: y: #D [string]: x: #D [string]: x: r: t: object: y: foo: t: object: { } bar: {} } // Cycle: x cyclic. The pattern constraint should not be seen as // "adding new structure", thereby permitting the cycle. noCancelSelfInvoke: t1: { y: [string]: b: y x: y x: c: x } // Even though these cycles cross pattern boundaries, they are still structural // cycles as the reference includes a field that triggers the pattern. selfTriggerCycle: _ // TODO: This does not show an explicit cycle within `a`, only a "child" cycle. // However, upon investigation this error is present in the tree. Either way, // the error only needs to be reported once, so this is not a huge problem. selfTriggerCycle: t1: { a: #T #T: { [string]: #T b: {} } } selfTriggerCycle: t2: { #T: [string]: X={ a: X } b: #T b: c: {} } selfTriggerCycle: long1: { // The long string of nested fields will initially exempt the structural // cycle, but they will eventually run out, causing the cycle to be // triggered. a: [string]: b: a // -> record conjunct from pattern per field. a: c: b: c: b: c: {} // -> track if any of the fields is not a cycle. } // TODO: see comment at selfTriggerCycle.t1 selfTriggerCycle: issue1503: { a: #T & { a: one: link: a: two: {} } #T: { a: [string]: link: #T a: b: {} } } mutuallyTriggeringCycle: t1: { // Even though y itself, as well as each of the x fields are not cyclic, // the combination of the two x conjuncts are, as the b fields of y will // trigger the pattern constraints in an interleaved fashion. y: [string]: b: y x: y x: c: y } -- ring.cue -- brokenRing: t1: { // NOTE that two permutations here have different results. That is less // of an issue than it seems, as the structural cycle is hidden behind // an optional path, which we generally allow. // TODO: it would be nicer, though, if the representation were consistent. p1: { D: a?: T T: b: D } p2: { T: b: D D: a?: T } } brokenRing: t2: p1: { D: [string]: T T: b: D } brokenRing: t2: p2: { T: b: D D: [string]: T } cyclicRing: t1: { D: a: T T: b: D } -- issue3476.cue -- issue3476: { #a: (#b & {x: _}).x #b: { x?: #c #c: [string]: #c } } -- issue3509.cue -- issue3509: { out: #job.step & "foo" #job: (#Workflow & {job: _}).job #Workflow: { job: step: string #matrixConfig: [...#matrixConfig] | string matrix?: [string]: [...#matrixConfig] } } -- out/compile -- --- in.cue { safeCycle: { simple2: { y: { [string]: { b: { c: 〈3;y〉 } } } x: 〈0;y〉 x: { c: 〈1;y〉 } } } safeCycle: { long1: { y: { [string]: { b: 〈2;y〉 } } x: 〈0;y〉 x: { c: { b: { e: { b: { c: _ } } } } } } } safeCycle: { long2: { a: { [string]: { b: 〈2;a〉 } } x: 〈0;a〉 x: { c: { b: { c: { b: { c: {} } } } } } } } noCyclePattern: _ noCyclePattern: { t1: { #D: { [string]: 〈1;#D〉 } a: {} [string]: 〈0;#D〉 [string]: { b: { c: {} } } } } noCyclePattern: { t2: { #D: { [string]: { x: 〈2;#D〉 } } a: {} [string]: 〈0;#D〉 [string]: { b: { x: { c: {} } } } } } noCyclePattern: { t3: { _D: { [string]: 〈1;_T〉 } _T: { x: 〈1;_D〉 } [string]: 〈0;_D〉 [string]: { b: { x: { c: {} } } } a: {} } } noCyclePattern: { t4: { _D: { [string]: { x: 〈2;_T〉 } } _T: { y: 〈1;_D〉 } [string]: 〈0;_D〉 [string]: { b: { x: {} } } a: {} } } noCyclePattern: { t5: { _D: { [string]: { x: 〈2;_T〉 } } _T: { y: 〈1;_D〉 } [string]: 〈0;_D〉 [string]: { b: { x: { y: { c: { x: {} } } } } } a: {} } } noCyclePattern: { t6: { #D: { [string]: 〈1;#E〉 } #E: { t: 〈1;#T〉 } #T: { { object: 〈2;#S〉 } } #S: { y: 〈1;#D〉 } [string]: { x: 〈1;#D〉 } [string]: { x: { r: { t: { object: { y: { foo: { t: { object: {} } } } } } } } } bar: {} } } noCancelSelfInvoke: { t1: { y: { [string]: { b: 〈2;y〉 } } x: 〈0;y〉 x: { c: 〈1;x〉 } } } selfTriggerCycle: _ selfTriggerCycle: { t1: { a: 〈0;#T〉 #T: { [string]: 〈1;#T〉 b: {} } } } selfTriggerCycle: { t2: { #T: { [string]: { a: 〈1〉 } } b: 〈0;#T〉 b: { c: {} } } } selfTriggerCycle: { long1: { a: { [string]: { b: 〈2;a〉 } } a: { c: { b: { c: { b: { c: {} } } } } } } } selfTriggerCycle: { issue1503: { a: (〈0;#T〉 & { a: { one: { link: { a: { two: {} } } } } }) #T: { a: { [string]: { link: 〈3;#T〉 } } a: { b: {} } } } } mutuallyTriggeringCycle: { t1: { y: { [string]: { b: 〈2;y〉 } } x: 〈0;y〉 x: { c: 〈1;y〉 } } } } --- issue3476.cue { issue3476: { #a: (〈0;#b〉 & { x: _ }).x #b: { x?: 〈0;#c〉 #c: { [string]: 〈1;#c〉 } } } } --- issue3509.cue { issue3509: { out: (〈0;#job〉.step & "foo") #job: (〈0;#Workflow〉 & { job: _ }).job #Workflow: { job: { step: string } #matrixConfig: ([ ...〈1;#matrixConfig〉, ]|string) matrix?: { [string]: [ ...〈2;#matrixConfig〉, ] } } } } --- ring.cue { brokenRing: { t1: { p1: { D: { a?: 〈1;T〉 } T: { b: 〈1;D〉 } } p2: { T: { b: 〈1;D〉 } D: { a?: 〈1;T〉 } } } } brokenRing: { t2: { p1: { D: { [string]: 〈1;T〉 } T: { b: 〈1;D〉 } } } } brokenRing: { t2: { p2: { T: { b: 〈1;D〉 } D: { [string]: 〈1;T〉 } } } } cyclicRing: { t1: { D: { a: 〈1;T〉 } T: { b: 〈1;D〉 } } } } -- out/eval/stats -- Leaks: 2 Freed: 193 Reused: 182 Allocs: 13 Retain: 20 Unifications: 193 Conjuncts: 399 Disjuncts: 213 -- out/evalalpha -- Errors: brokenRing.t1.p1.T.b: structural cycle cyclicRing.t1.T.b: structural cycle mutuallyTriggeringCycle.t1.x.c.b.b.b.b.b: structural cycle noCancelSelfInvoke.t1.x.c.b.b: structural cycle noCancelSelfInvoke.t1.x.c.c: structural cycle selfTriggerCycle.issue1503.#T.a.b.link: structural cycle selfTriggerCycle.long1.a.c.b.c.b.c.b: structural cycle selfTriggerCycle.t1.#T.b.b: structural cycle selfTriggerCycle.t2.b.c.a: structural cycle Result: (_|_){ // [structural cycle] safeCycle: (struct){ simple2: (struct){ y: (struct){ } x: (struct){ c: (struct){ b: (struct){ c: (struct){ } b: (struct){ c: (struct){ } } } } } } long1: (struct){ y: (struct){ } x: (struct){ c: (struct){ b: (struct){ e: (struct){ b: (struct){ c: (struct){ b: (struct){ } } } } } } } } long2: (struct){ a: (struct){ } x: (struct){ c: (struct){ b: (struct){ c: (struct){ b: (struct){ c: (struct){ b: (struct){ } } } } } } } } } noCyclePattern: (struct){ t1: (struct){ #D: (#struct){ } a: (#struct){ b: (#struct){ c: (#struct){ } } } } t2: (struct){ #D: (#struct){ } a: (#struct){ b: (#struct){ x: (#struct){ c: (#struct){ x: (#struct){ } } } } } } t3: (struct){ _D: (struct){ } _T: (struct){ x: (struct){ } } a: (struct){ b: (struct){ x: (struct){ c: (struct){ x: (struct){ } } } } } } t4: (struct){ _D: (struct){ } _T: (struct){ y: (struct){ } } a: (struct){ b: (struct){ x: (struct){ y: (struct){ } } } } } t5: (struct){ _D: (struct){ } _T: (struct){ y: (struct){ } } a: (struct){ b: (struct){ x: (struct){ y: (struct){ c: (struct){ x: (struct){ y: (struct){ } } } } } } } } t6: (struct){ #D: (#struct){ } #E: (#struct){ t: ~(noCyclePattern.t6.#T) } #T: (#struct){ object: ~(noCyclePattern.t6.#S) } #S: (#struct){ y: (#struct){ } } bar: (struct){ x: (#struct){ r: (#struct){ t: (#struct){ object: (#struct){ y: (#struct){ foo: (#struct){ t: (#struct){ object: (#struct){ y: (#struct){ } } } } } } } } } } } } noCancelSelfInvoke: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] y: (struct){ } x: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] noCancelSelfInvoke.t1.x.c.b.b: structural cycle } } c: (_|_){ // [structural cycle] noCancelSelfInvoke.t1.x.c.c: structural cycle } } } } } selfTriggerCycle: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] a: ~(selfTriggerCycle.t1.#T) #T: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] selfTriggerCycle.t1.#T.b.b: structural cycle } } } } t2: (_|_){ // [structural cycle] #T: (#struct){ } b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] selfTriggerCycle.t2.b.c.a: structural cycle } } } } long1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] selfTriggerCycle.long1.a.c.b.c.b.c.b: structural cycle } } } } } } } } issue1503: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] one: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] two: (_|_){ // [structural cycle] link: ~(selfTriggerCycle.issue1503.#T) } b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] } } } } } b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] } } } } #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] selfTriggerCycle.issue1503.#T.a.b.link: structural cycle } } } } } } mutuallyTriggeringCycle: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] y: (struct){ } x: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] mutuallyTriggeringCycle.t1.x.c.b.b.b.b.b: structural cycle } } } } } } } } } issue3476: (struct){ #a: (#struct){ } #b: (#struct){ x?: (#struct){ } #c: (#struct){ } } } issue3509: (struct){ out: (string){ "foo" } #job: (#struct){ step: (string){ string } } #Workflow: (#struct){ job: (#struct){ step: (string){ string } } #matrixConfig: ((string|list)){ |((list){ }, (string){ string }) } matrix?: (#struct){ } } } brokenRing: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] p1: (_|_){ // [structural cycle] D: (struct){ a?: ~(brokenRing.t1.p1.T) } T: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] brokenRing.t1.p1.T.b: structural cycle } } } p2: (struct){ T: (struct){ b: ~(brokenRing.t1.p2.D) } D: (struct){ a?: (_|_){ // [structural cycle] brokenRing.t1.p2.D.a: structural cycle } } } } t2: (struct){ p1: (struct){ D: (struct){ } T: (struct){ b: (struct){ } } } p2: (struct){ T: (struct){ b: (struct){ } } D: (struct){ } } } } cyclicRing: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] D: (_|_){ // [structural cycle] a: ~(cyclicRing.t1.T) } T: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] cyclicRing.t1.T.b: structural cycle } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,12 +1,11 @@ Errors: brokenRing.t1.p1.T.b: structural cycle -cyclicRing.t1.D.a.b: structural cycle cyclicRing.t1.T.b: structural cycle -mutuallyTriggeringCycle.t1.x.c.b.b.b.b: structural cycle -noCancelSelfInvoke.t1.x.c.b.b.b: structural cycle +mutuallyTriggeringCycle.t1.x.c.b.b.b.b.b: structural cycle +noCancelSelfInvoke.t1.x.c.b.b: structural cycle noCancelSelfInvoke.t1.x.c.c: structural cycle selfTriggerCycle.issue1503.#T.a.b.link: structural cycle -selfTriggerCycle.long1.a.c.b.c.b.c.b.c.b: structural cycle +selfTriggerCycle.long1.a.c.b.c.b.c.b: structural cycle selfTriggerCycle.t1.#T.b.b: structural cycle selfTriggerCycle.t2.b.c.a: structural cycle @@ -152,18 +151,10 @@ #D: (#struct){ } #E: (#struct){ - t: (#struct){ - object: (#struct){ - y: (#struct){ - } - } - } - } - #T: (#struct){ - object: (#struct){ - y: (#struct){ - } - } + t: ~(noCyclePattern.t6.#T) + } + #T: (#struct){ + object: ~(noCyclePattern.t6.#S) } #S: (#struct){ y: (#struct){ @@ -201,18 +192,15 @@ // [structural cycle] c: (_|_){ // [structural cycle] + b: (_|_){ + // [structural cycle] + b: (_|_){ + // [structural cycle] noCancelSelfInvoke.t1.x.c.b.b: structural cycle + } + } c: (_|_){ // [structural cycle] noCancelSelfInvoke.t1.x.c.c: structural cycle } - b: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] noCancelSelfInvoke.t1.x.c.b.b.b: structural cycle - } - } - } } } } @@ -221,12 +209,7 @@ // [structural cycle] t1: (_|_){ // [structural cycle] - a: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] - } - } + a: ~(selfTriggerCycle.t1.#T) #T: (_|_){ // [structural cycle] b: (_|_){ @@ -266,13 +249,7 @@ c: (_|_){ // [structural cycle] b: (_|_){ - // [structural cycle] - c: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] selfTriggerCycle.long1.a.c.b.c.b.c.b.c.b: structural cycle - } - } + // [structural cycle] selfTriggerCycle.long1.a.c.b.c.b.c.b: structural cycle } } } @@ -287,20 +264,29 @@ // [structural cycle] a: (_|_){ // [structural cycle] - b: (_|_){ - // [structural cycle] - link: (_|_){ - // [structural cycle] - } - } one: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] - a: (struct){ - two: (struct){ - } - } + a: (_|_){ + // [structural cycle] + two: (_|_){ + // [structural cycle] + link: ~(selfTriggerCycle.issue1503.#T) + } + b: (_|_){ + // [structural cycle] + link: (_|_){ + // [structural cycle] + } + } + } + } + } + b: (_|_){ + // [structural cycle] + link: (_|_){ + // [structural cycle] } } } @@ -336,7 +322,10 @@ b: (_|_){ // [structural cycle] b: (_|_){ - // [structural cycle] mutuallyTriggeringCycle.t1.x.c.b.b.b.b: structural cycle + // [structural cycle] + b: (_|_){ + // [structural cycle] mutuallyTriggeringCycle.t1.x.c.b.b.b.b.b: structural cycle + } } } } @@ -377,12 +366,7 @@ p1: (_|_){ // [structural cycle] D: (struct){ - a?: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] brokenRing.t1.p1.D.a.b: structural cycle - } - } + a?: ~(brokenRing.t1.p1.T) } T: (_|_){ // [structural cycle] @@ -393,11 +377,7 @@ } p2: (struct){ T: (struct){ - b: (struct){ - a?: (_|_){ - // [structural cycle] brokenRing.t1.p2.T.b.a: structural cycle - } - } + b: ~(brokenRing.t1.p2.D) } D: (struct){ a?: (_|_){ @@ -431,12 +411,7 @@ // [structural cycle] D: (_|_){ // [structural cycle] - a: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] cyclicRing.t1.D.a.b: structural cycle - } - } + a: ~(cyclicRing.t1.T) } T: (_|_){ // [structural cycle] -- diff/todo/p2 -- selfTriggerCycle.t1.a.b.b: cycle detected slightly too late -- out/eval -- Errors: brokenRing.t1.p1.T.b: structural cycle cyclicRing.t1.D.a.b: structural cycle cyclicRing.t1.T.b: structural cycle mutuallyTriggeringCycle.t1.x.c.b.b.b.b: structural cycle noCancelSelfInvoke.t1.x.c.b.b.b: structural cycle noCancelSelfInvoke.t1.x.c.c: structural cycle selfTriggerCycle.issue1503.#T.a.b.link: structural cycle selfTriggerCycle.long1.a.c.b.c.b.c.b.c.b: structural cycle selfTriggerCycle.t1.#T.b.b: structural cycle selfTriggerCycle.t2.b.c.a: structural cycle Result: (_|_){ // [structural cycle] safeCycle: (struct){ simple2: (struct){ y: (struct){ } x: (struct){ c: (struct){ b: (struct){ c: (struct){ } b: (struct){ c: (struct){ } } } } } } long1: (struct){ y: (struct){ } x: (struct){ c: (struct){ b: (struct){ e: (struct){ b: (struct){ c: (struct){ b: (struct){ } } } } } } } } long2: (struct){ a: (struct){ } x: (struct){ c: (struct){ b: (struct){ c: (struct){ b: (struct){ c: (struct){ b: (struct){ } } } } } } } } } noCyclePattern: (struct){ t1: (struct){ #D: (#struct){ } a: (#struct){ b: (#struct){ c: (#struct){ } } } } t2: (struct){ #D: (#struct){ } a: (#struct){ b: (#struct){ x: (#struct){ c: (#struct){ x: (#struct){ } } } } } } t3: (struct){ _D: (struct){ } _T: (struct){ x: (struct){ } } a: (struct){ b: (struct){ x: (struct){ c: (struct){ x: (struct){ } } } } } } t4: (struct){ _D: (struct){ } _T: (struct){ y: (struct){ } } a: (struct){ b: (struct){ x: (struct){ y: (struct){ } } } } } t5: (struct){ _D: (struct){ } _T: (struct){ y: (struct){ } } a: (struct){ b: (struct){ x: (struct){ y: (struct){ c: (struct){ x: (struct){ y: (struct){ } } } } } } } } t6: (struct){ #D: (#struct){ } #E: (#struct){ t: (#struct){ object: (#struct){ y: (#struct){ } } } } #T: (#struct){ object: (#struct){ y: (#struct){ } } } #S: (#struct){ y: (#struct){ } } bar: (struct){ x: (#struct){ r: (#struct){ t: (#struct){ object: (#struct){ y: (#struct){ foo: (#struct){ t: (#struct){ object: (#struct){ y: (#struct){ } } } } } } } } } } } } noCancelSelfInvoke: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] y: (struct){ } x: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] noCancelSelfInvoke.t1.x.c.c: structural cycle } b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] noCancelSelfInvoke.t1.x.c.b.b.b: structural cycle } } } } } } } selfTriggerCycle: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] } } #T: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] selfTriggerCycle.t1.#T.b.b: structural cycle } } } } t2: (_|_){ // [structural cycle] #T: (#struct){ } b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] selfTriggerCycle.t2.b.c.a: structural cycle } } } } long1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] selfTriggerCycle.long1.a.c.b.c.b.c.b.c.b: structural cycle } } } } } } } } } } issue1503: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] } } one: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] a: (struct){ two: (struct){ } } } } } } #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] selfTriggerCycle.issue1503.#T.a.b.link: structural cycle } } } } } } mutuallyTriggeringCycle: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] y: (struct){ } x: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] mutuallyTriggeringCycle.t1.x.c.b.b.b.b: structural cycle } } } } } } } } issue3476: (struct){ #a: (#struct){ } #b: (#struct){ x?: (#struct){ } #c: (#struct){ } } } issue3509: (struct){ out: (string){ "foo" } #job: (#struct){ step: (string){ string } } #Workflow: (#struct){ job: (#struct){ step: (string){ string } } #matrixConfig: ((string|list)){ |((list){ }, (string){ string }) } matrix?: (#struct){ } } } brokenRing: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] p1: (_|_){ // [structural cycle] D: (struct){ a?: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] brokenRing.t1.p1.D.a.b: structural cycle } } } T: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] brokenRing.t1.p1.T.b: structural cycle } } } p2: (struct){ T: (struct){ b: (struct){ a?: (_|_){ // [structural cycle] brokenRing.t1.p2.T.b.a: structural cycle } } } D: (struct){ a?: (_|_){ // [structural cycle] brokenRing.t1.p2.D.a: structural cycle } } } } t2: (struct){ p1: (struct){ D: (struct){ } T: (struct){ b: (struct){ } } } p2: (struct){ T: (struct){ b: (struct){ } } D: (struct){ } } } } cyclicRing: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] D: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] cyclicRing.t1.D.a.b: structural cycle } } } T: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] cyclicRing.t1.T.b: structural cycle } } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/cycle_with_bounds.txtar000066400000000000000000000006741474664451600247630ustar00rootroot00000000000000-- in.cue -- #Value: int foo: #Value foo: !=bar bar: #Value bar: !=foo bar: 0 foo: 1 -- out/compile -- --- in.cue { #Value: int foo: 〈0;#Value〉 foo: !=〈0;bar〉 bar: 〈0;#Value〉 bar: !=〈0;foo〉 bar: 0 foo: 1 } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 1 Allocs: 3 Retain: 1 Unifications: 4 Conjuncts: 9 Disjuncts: 4 -- out/eval -- (struct){ #Value: (int){ int } foo: (int){ 1 } bar: (int){ 0 } } cue-lang-cue-db9cc73/cue/testdata/cycle/disjunction.txtar000066400000000000000000000163021474664451600236030ustar00rootroot00000000000000-- in.cue -- // cycle is a structural cycle cycle: a: cycle // reference to outside structural cycle r1a: cycle | int r1b: int | cycle r2a: cycle | 1 r2b: 1 | cycle r3a: cycle | null r3b: null | cycle r4a: cycle | {} r4b: {} | cycle r5a: cycle | [] r5b: [] | cycle // reference to ancestor node s1a: x: s1a | int s1b: x: int | s1b s2a: x: s2a | 1 s2b: x: 1 | s2b s3a: x: s3a | null s3b: x: null | s3b s4a: x: s4a | {} s4b: x: {} | s4b s5a: x: s5a | [] s5b: x: [] | s5b -- issue3042.cue -- issue3042: { // Recursively, any field named "name" should begin with "foo". // The data value below should then fail. #foo: =~"^foo" #nesting: string | {name?: #foo, [string]: #nesting} | [...#nesting] data: #nesting & { secret: { infra: [ {name: "bar1"} ] } } } -- out/eval/stats -- Leaks: 0 Freed: 199 Reused: 181 Allocs: 18 Retain: 0 Unifications: 93 Conjuncts: 280 Disjuncts: 199 -- out/eval -- Errors: cycle.a: structural cycle Result: (_|_){ // [structural cycle] cycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] cycle.a: structural cycle } } r1a: (int){ int } r1b: (int){ int } r2a: (int){ 1 } r2b: (int){ 1 } r3a: (null){ null } r3b: (null){ null } r4a: (struct){ } r4b: (struct){ } r5a: (#list){ } r5b: (#list){ } s1a: (struct){ x: (int){ int } } s1b: (struct){ x: (int){ int } } s2a: (struct){ x: (int){ 1 } } s2b: (struct){ x: (int){ 1 } } s3a: (struct){ x: (null){ null } } s3b: (struct){ x: (null){ null } } s4a: (struct){ x: (struct){ } } s4b: (struct){ x: (struct){ } } s5a: (struct){ x: (#list){ } } s5b: (struct){ x: (#list){ } } issue3042: (struct){ #foo: (string){ =~"^foo" } #nesting: ((string|list|struct)){ |((string){ string }, (#struct){ name?: (string){ =~"^foo" } }, (list){ }) } data: (#struct){ secret: (#struct){ infra: (#list){ 0: (struct){ name: (string){ "bar1" } } } name?: (string){ =~"^foo" } } name?: (string){ =~"^foo" } } } } -- out/evalalpha -- Errors: cycle.a: structural cycle issue3042.data: 3 errors in empty disjunction: issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct): ./issue3042.cue:5:57 ./issue3042.cue:7:19 issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct): ./issue3042.cue:5:12 ./issue3042.cue:7:19 issue3042.data.secret: field not allowed: ./issue3042.cue:8:3 Result: (_|_){ // [eval] cycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] cycle.a: structural cycle } } r1a: (int){ int } r1b: (int){ int } r2a: (int){ 1 } r2b: (int){ 1 } r3a: (null){ null } r3b: (null){ null } r4a: (struct){ } r4b: (struct){ } r5a: (#list){ } r5b: (#list){ } s1a: (struct){ x: (int){ int } } s1b: (struct){ x: (int){ int } } s2a: (struct){ x: (int){ 1 } } s2b: (struct){ x: (int){ 1 } } s3a: (struct){ x: (null){ null } } s3b: (struct){ x: (null){ null } } s4a: (struct){ x: (struct){ } } s4b: (struct){ x: (struct){ } } s5a: (struct){ x: (#list){ } } s5b: (struct){ x: (#list){ } } issue3042: (_|_){ // [eval] #foo: (string){ =~"^foo" } #nesting: ((string|list|struct)){ |((string){ string }, (#struct){ name?: (string){ =~"^foo" } }, (list){ }) } data: (_|_){ // [eval] issue3042.data: 3 errors in empty disjunction: // issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct): // ./issue3042.cue:5:57 // ./issue3042.cue:7:19 // issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct): // ./issue3042.cue:5:12 // ./issue3042.cue:7:19 // issue3042.data.secret: field not allowed: // ./issue3042.cue:8:3 secret: (struct){ infra: (list){ list } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,18 @@ Errors: cycle.a: structural cycle +issue3042.data: 3 errors in empty disjunction: +issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct): + ./issue3042.cue:5:57 + ./issue3042.cue:7:19 +issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct): + ./issue3042.cue:5:12 + ./issue3042.cue:7:19 +issue3042.data.secret: field not allowed: + ./issue3042.cue:8:3 Result: (_|_){ - // [structural cycle] + // [eval] cycle: (_|_){ // [structural cycle] a: (_|_){ @@ -58,22 +67,26 @@ x: (#list){ } } - issue3042: (struct){ + issue3042: (_|_){ + // [eval] #foo: (string){ =~"^foo" } #nesting: ((string|list|struct)){ |((string){ string }, (#struct){ name?: (string){ =~"^foo" } }, (list){ }) } - data: (#struct){ - secret: (#struct){ - infra: (#list){ - 0: (struct){ - name: (string){ "bar1" } - } - } - name?: (string){ =~"^foo" } + data: (_|_){ + // [eval] issue3042.data: 3 errors in empty disjunction: + // issue3042.data: conflicting values [...#nesting] and {secret:{infra:[{name:"bar1"}]}} (mismatched types list and struct): + // ./issue3042.cue:5:57 + // ./issue3042.cue:7:19 + // issue3042.data: conflicting values string and {secret:{infra:[{name:"bar1"}]}} (mismatched types string and struct): + // ./issue3042.cue:5:12 + // ./issue3042.cue:7:19 + // issue3042.data.secret: field not allowed: + // ./issue3042.cue:8:3 + secret: (struct){ + infra: (list){ list } } - name?: (string){ =~"^foo" } } } } -- diff/explanation -- issue3042: The old evaluator incorrectly resolved to a concrete value, whereas the new evaluator correctly spots that data.secret.infra.name does not unify with #foo. -- out/compile -- --- in.cue { cycle: { a: 〈1;cycle〉 } r1a: (〈0;cycle〉|int) r1b: (int|〈0;cycle〉) r2a: (〈0;cycle〉|1) r2b: (1|〈0;cycle〉) r3a: (〈0;cycle〉|null) r3b: (null|〈0;cycle〉) r4a: (〈0;cycle〉|{}) r4b: ({}|〈0;cycle〉) r5a: (〈0;cycle〉|[]) r5b: ([]|〈0;cycle〉) s1a: { x: (〈1;s1a〉|int) } s1b: { x: (int|〈1;s1b〉) } s2a: { x: (〈1;s2a〉|1) } s2b: { x: (1|〈1;s2b〉) } s3a: { x: (〈1;s3a〉|null) } s3b: { x: (null|〈1;s3b〉) } s4a: { x: (〈1;s4a〉|{}) } s4b: { x: ({}|〈1;s4b〉) } s5a: { x: (〈1;s5a〉|[]) } s5b: { x: ([]|〈1;s5b〉) } } --- issue3042.cue { issue3042: { #foo: =~"^foo" #nesting: (string|{ name?: 〈1;#foo〉 [string]: 〈1;#nesting〉 }|[ ...〈1;#nesting〉, ]) data: (〈0;#nesting〉 & { secret: { infra: [ { name: "bar1" }, ] } }) } } cue-lang-cue-db9cc73/cue/testdata/cycle/evaluate.txtar000066400000000000000000000467511474664451600230730ustar00rootroot00000000000000-- in.cue -- // All these cases whose name end with cycle should fail with a structural // error. These are all uncommon code paths, triggered when container types // are evalated within a nested expression such as as an argument to a // function call. // // The builtins are typically used to trigger the uncommon path. The choice of // builtin is irrelevant, as long as they don't finalize args before processing. import "list" // This is a resolvable reference cycle, were b is equated to c. letCycleOK: t1: { b: c let X = b c: X } // The let has structural cycle, but it is only used in a way that the // structural cycle is avoided. letCycleOK: t2: { a: { b: 1 let X = a c: X.b } } // Ensure that the cycle exemption algorithm does not bypass actual structural // cycles. letCycleFail: t1: { a: { b: 1 let X = a c: X } } // Cycles should also be detected in evaluation paths that descend into // recursion at non-field boundaries. letCycleFail: t2: { a: { let X = a if X == _|_ { } x: y: "" } } listCycleOK: { a: b b: and([c]) c: a } disjunctionCycle: { a: b b: and(1 | c) c: a } forCycle: { #A: a: #B // TODO(errors): Correct error position. #B: or([for x in #A { b: x }]) } letCycleWithAnd: { a: d: b b: and([for x in a let y = x { y }]) c: a } closeCycle: { a: b b: close({d: c}) c: a } structCycle: { a: b b: and([{d: c}]) c: a } embedCycle: { a: b b: close({c}) c: a } listAddCycle: { a: b b: list.Concat([[c], [c]]) c: a } listMulCycle: { a: b b: list.Repeat([{a: b: c}], 3) c: a } // consult the correct closeness info in the face of it being passed down // from parent. closeFail: { #T: [_]: _ #T: close({"a": string}) x: #T x: b: "foo" } printCycle: { a: { X: a if X { } } } -- out/eval/stats -- Leaks: 48 Freed: 127 Reused: 120 Allocs: 55 Retain: 138 Unifications: 163 Conjuncts: 299 Disjuncts: 192 -- out/evalalpha -- Errors: closeCycle.c: structural cycle letCycleFail.t1.a.c: structural cycle printCycle.a.X: structural cycle structCycle.c: structural cycle disjunctionCycle.b: cannot use 1 (type int) as type list: ./in.cue:56:5 ./in.cue:56:9 b: structural cycle: ./in.cue:62:6 structural cycle: ./in.cue:85:12 listAddCycle.c: structural cycle: ./in.cue:91:5 listMulCycle.c: structural cycle: ./in.cue:97:5 closeFail.x.b: field not allowed: ./in.cue:105:6 ./in.cue:104:6 ./in.cue:107:5 Result: (_|_){ // [eval] letCycleOK: (struct){ t1: (struct){ b: (_){ _ } let X#1 = (_){ _ } c: (_){ _ } } t2: (struct){ a: (struct){ b: (int){ 1 } let X#2 = (_|_){ // [structural cycle] letCycleOK.t2.a.X: structural cycle } c: (int){ 1 } } } } letCycleFail: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (int){ 1 } let X#3 = (_|_){ // [structural cycle] letCycleFail.t1.a.X: structural cycle } c: (_|_){ // [structural cycle] letCycleFail.t1.a.c: structural cycle } } } t2: (struct){ a: (struct){ let X#4 = (_|_){ // [structural cycle] letCycleFail.t2.a.X: structural cycle: // ./in.cue:43:6 } x: (struct){ y: (string){ "" } } } } } listCycleOK: (struct){ a: (_){ _ } b: (_){ _ } c: (_){ _ } } disjunctionCycle: (_|_){ // [eval] a: (_|_){ // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } b: (_|_){ // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } c: (_|_){ // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } } forCycle: (_|_){ // [structural cycle] #A: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: structural cycle: // ./in.cue:62:6 } } #B: (_|_){ // [structural cycle] b: structural cycle: // ./in.cue:62:6 } } letCycleWithAnd: (struct){ a: (struct){ d: (struct){ } } b: (struct){ } c: ~(letCycleWithAnd.a) } closeCycle: (_|_){ // [structural cycle] a: ~(closeCycle.b) b: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] closeCycle.c: structural cycle } } c: (_|_){ // [structural cycle] closeCycle.c: structural cycle } } structCycle: (_|_){ // [structural cycle] a: ~(structCycle.b) b: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] structCycle.c: structural cycle } } c: (_|_){ // [structural cycle] structCycle.c: structural cycle } } embedCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] structural cycle: // ./in.cue:85:12 } b: (_|_){ // [structural cycle] structural cycle: // ./in.cue:85:12 } c: (_|_){ // [structural cycle] structural cycle: // ./in.cue:85:12 } } listAddCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] listAddCycle.c: structural cycle: // ./in.cue:91:5 } b: (_|_){ // [structural cycle] listAddCycle.c: structural cycle: // ./in.cue:91:5 } c: (_|_){ // [structural cycle] listAddCycle.c: structural cycle: // ./in.cue:91:5 } } listMulCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] listMulCycle.c: structural cycle: // ./in.cue:97:5 } b: (_|_){ // [structural cycle] listMulCycle.c: structural cycle: // ./in.cue:97:5 } c: (_|_){ // [structural cycle] listMulCycle.c: structural cycle: // ./in.cue:97:5 } } closeFail: (_|_){ // [eval] #T: (#struct){ a: (string){ string } } x: (_|_){ // [eval] b: (_|_){ // [eval] closeFail.x.b: field not allowed: // ./in.cue:105:6 // ./in.cue:104:6 // ./in.cue:107:5 } a: (string){ string } } } printCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] X: (_|_){ // [structural cycle] printCycle.a.X: structural cycle } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,33 +1,23 @@ Errors: -closeCycle.a: structural cycle -closeCycle.b.d: structural cycle -closeFail.x.b: field not allowed: - ./in.cue:104:6 - ./in.cue:105:12 - ./in.cue:106:6 - ./in.cue:107:5 +closeCycle.c: structural cycle letCycleFail.t1.a.c: structural cycle -structCycle.a: structural cycle -structCycle.b.d: structural cycle -disjunctionCycle.a: cannot use 1 (type int) as type list: - ./in.cue:56:5 - ./in.cue:56:9 +printCycle.a.X: structural cycle +structCycle.c: structural cycle disjunctionCycle.b: cannot use 1 (type int) as type list: ./in.cue:56:5 ./in.cue:56:9 -disjunctionCycle.c: cannot use 1 (type int) as type list: - ./in.cue:56:5 - ./in.cue:56:9 b: structural cycle: ./in.cue:62:6 -closeCycle.c: structural cycle: - ./in.cue:73:15 -structCycle.c: structural cycle: - ./in.cue:79:14 -embedCycle: structural cycle: - ./in.cue:85:11 -printCycle.a.X.X: structural cycle: - ./in.cue:113:6 +structural cycle: + ./in.cue:85:12 +listAddCycle.c: structural cycle: + ./in.cue:91:5 +listMulCycle.c: structural cycle: + ./in.cue:97:5 +closeFail.x.b: field not allowed: + ./in.cue:105:6 + ./in.cue:104:6 + ./in.cue:107:5 Result: (_|_){ @@ -65,14 +55,9 @@ } t2: (struct){ a: (struct){ - let X#4 = (struct){ - let X#4 = (_|_){ - // [structural cycle] letCycleFail.t2.a.X.X: structural cycle: - // ./in.cue:43:6 - } - x: (struct){ - y: (string){ "" } - } + let X#4 = (_|_){ + // [structural cycle] letCycleFail.t2.a.X: structural cycle: + // ./in.cue:43:6 } x: (struct){ y: (string){ "" } @@ -88,17 +73,17 @@ disjunctionCycle: (_|_){ // [eval] a: (_|_){ - // [eval] disjunctionCycle.a: cannot use 1 (type int) as type list: - // ./in.cue:56:5 - // ./in.cue:56:9 - } - b: (_|_){ - // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: - // ./in.cue:56:5 - // ./in.cue:56:9 - } - c: (_|_){ - // [eval] disjunctionCycle.c: cannot use 1 (type int) as type list: + // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: + // ./in.cue:56:5 + // ./in.cue:56:9 + } + b: (_|_){ + // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: + // ./in.cue:56:5 + // ./in.cue:56:9 + } + c: (_|_){ + // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } @@ -124,80 +109,77 @@ } b: (struct){ } - c: (struct){ - d: (struct){ - } - } + c: ~(letCycleWithAnd.a) } closeCycle: (_|_){ // [structural cycle] - a: (_|_){ - // [structural cycle] closeCycle.a: structural cycle - } - b: (_|_){ - // [structural cycle] - d: (_|_){ - // [structural cycle] closeCycle.b.d: structural cycle - } - } - c: (_|_){ - // [structural cycle] closeCycle.c: structural cycle: - // ./in.cue:73:15 + a: ~(closeCycle.b) + b: (_|_){ + // [structural cycle] + d: (_|_){ + // [structural cycle] closeCycle.c: structural cycle + } + } + c: (_|_){ + // [structural cycle] closeCycle.c: structural cycle } } structCycle: (_|_){ // [structural cycle] - a: (_|_){ - // [structural cycle] structCycle.a: structural cycle - } - b: (_|_){ - // [structural cycle] - d: (_|_){ - // [structural cycle] structCycle.b.d: structural cycle - } - } - c: (_|_){ - // [structural cycle] structCycle.c: structural cycle: - // ./in.cue:79:14 + a: ~(structCycle.b) + b: (_|_){ + // [structural cycle] + d: (_|_){ + // [structural cycle] structCycle.c: structural cycle + } + } + c: (_|_){ + // [structural cycle] structCycle.c: structural cycle } } embedCycle: (_|_){ // [structural cycle] a: (_|_){ - // [structural cycle] embedCycle: structural cycle: - // ./in.cue:85:11 - } - b: (_|_){ - // [structural cycle] embedCycle: structural cycle: - // ./in.cue:85:11 - } - c: (_|_){ - // [structural cycle] embedCycle: structural cycle: - // ./in.cue:85:11 + // [structural cycle] structural cycle: + // ./in.cue:85:12 + } + b: (_|_){ + // [structural cycle] structural cycle: + // ./in.cue:85:12 + } + c: (_|_){ + // [structural cycle] structural cycle: + // ./in.cue:85:12 } } listAddCycle: (_|_){ // [structural cycle] a: (_|_){ - // [structural cycle] - } - b: (_|_){ - // [structural cycle] - } - c: (_|_){ - // [structural cycle] + // [structural cycle] listAddCycle.c: structural cycle: + // ./in.cue:91:5 + } + b: (_|_){ + // [structural cycle] listAddCycle.c: structural cycle: + // ./in.cue:91:5 + } + c: (_|_){ + // [structural cycle] listAddCycle.c: structural cycle: + // ./in.cue:91:5 } } listMulCycle: (_|_){ // [structural cycle] a: (_|_){ - // [structural cycle] - } - b: (_|_){ - // [structural cycle] - } - c: (_|_){ - // [structural cycle] + // [structural cycle] listMulCycle.c: structural cycle: + // ./in.cue:97:5 + } + b: (_|_){ + // [structural cycle] listMulCycle.c: structural cycle: + // ./in.cue:97:5 + } + c: (_|_){ + // [structural cycle] listMulCycle.c: structural cycle: + // ./in.cue:97:5 } } closeFail: (_|_){ @@ -207,21 +189,22 @@ } x: (_|_){ // [eval] - a: (string){ string } b: (_|_){ // [eval] closeFail.x.b: field not allowed: + // ./in.cue:105:6 // ./in.cue:104:6 - // ./in.cue:105:12 - // ./in.cue:106:6 // ./in.cue:107:5 } + a: (string){ string } } } printCycle: (_|_){ // [structural cycle] a: (_|_){ - // [structural cycle] printCycle.a.X.X: structural cycle: - // ./in.cue:113:6 + // [structural cycle] + X: (_|_){ + // [structural cycle] printCycle.a.X: structural cycle + } } } } -- out/eval -- Errors: closeCycle.a: structural cycle closeCycle.b.d: structural cycle closeFail.x.b: field not allowed: ./in.cue:104:6 ./in.cue:105:12 ./in.cue:106:6 ./in.cue:107:5 letCycleFail.t1.a.c: structural cycle structCycle.a: structural cycle structCycle.b.d: structural cycle disjunctionCycle.a: cannot use 1 (type int) as type list: ./in.cue:56:5 ./in.cue:56:9 disjunctionCycle.b: cannot use 1 (type int) as type list: ./in.cue:56:5 ./in.cue:56:9 disjunctionCycle.c: cannot use 1 (type int) as type list: ./in.cue:56:5 ./in.cue:56:9 b: structural cycle: ./in.cue:62:6 closeCycle.c: structural cycle: ./in.cue:73:15 structCycle.c: structural cycle: ./in.cue:79:14 embedCycle: structural cycle: ./in.cue:85:11 printCycle.a.X.X: structural cycle: ./in.cue:113:6 Result: (_|_){ // [eval] letCycleOK: (struct){ t1: (struct){ b: (_){ _ } let X#1 = (_){ _ } c: (_){ _ } } t2: (struct){ a: (struct){ b: (int){ 1 } let X#2 = (_|_){ // [structural cycle] letCycleOK.t2.a.X: structural cycle } c: (int){ 1 } } } } letCycleFail: (_|_){ // [structural cycle] t1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (int){ 1 } let X#3 = (_|_){ // [structural cycle] letCycleFail.t1.a.X: structural cycle } c: (_|_){ // [structural cycle] letCycleFail.t1.a.c: structural cycle } } } t2: (struct){ a: (struct){ let X#4 = (struct){ let X#4 = (_|_){ // [structural cycle] letCycleFail.t2.a.X.X: structural cycle: // ./in.cue:43:6 } x: (struct){ y: (string){ "" } } } x: (struct){ y: (string){ "" } } } } } listCycleOK: (struct){ a: (_){ _ } b: (_){ _ } c: (_){ _ } } disjunctionCycle: (_|_){ // [eval] a: (_|_){ // [eval] disjunctionCycle.a: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } b: (_|_){ // [eval] disjunctionCycle.b: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } c: (_|_){ // [eval] disjunctionCycle.c: cannot use 1 (type int) as type list: // ./in.cue:56:5 // ./in.cue:56:9 } } forCycle: (_|_){ // [structural cycle] #A: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: structural cycle: // ./in.cue:62:6 } } #B: (_|_){ // [structural cycle] b: structural cycle: // ./in.cue:62:6 } } letCycleWithAnd: (struct){ a: (struct){ d: (struct){ } } b: (struct){ } c: (struct){ d: (struct){ } } } closeCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] closeCycle.a: structural cycle } b: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] closeCycle.b.d: structural cycle } } c: (_|_){ // [structural cycle] closeCycle.c: structural cycle: // ./in.cue:73:15 } } structCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] structCycle.a: structural cycle } b: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] structCycle.b.d: structural cycle } } c: (_|_){ // [structural cycle] structCycle.c: structural cycle: // ./in.cue:79:14 } } embedCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] embedCycle: structural cycle: // ./in.cue:85:11 } b: (_|_){ // [structural cycle] embedCycle: structural cycle: // ./in.cue:85:11 } c: (_|_){ // [structural cycle] embedCycle: structural cycle: // ./in.cue:85:11 } } listAddCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] } b: (_|_){ // [structural cycle] } c: (_|_){ // [structural cycle] } } listMulCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] } b: (_|_){ // [structural cycle] } c: (_|_){ // [structural cycle] } } closeFail: (_|_){ // [eval] #T: (#struct){ a: (string){ string } } x: (_|_){ // [eval] a: (string){ string } b: (_|_){ // [eval] closeFail.x.b: field not allowed: // ./in.cue:104:6 // ./in.cue:105:12 // ./in.cue:106:6 // ./in.cue:107:5 } } } printCycle: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] printCycle.a.X.X: structural cycle: // ./in.cue:113:6 } } } -- out/compile -- --- in.cue { letCycleOK: { t1: { b: 〈0;c〉 let X#1 = 〈0;b〉 c: 〈0;let X#1〉 } } letCycleOK: { t2: { a: { b: 1 let X#2 = 〈1;a〉 c: 〈0;let X#2〉.b } } } letCycleFail: { t1: { a: { b: 1 let X#3 = 〈1;a〉 c: 〈0;let X#3〉 } } } letCycleFail: { t2: { a: { let X#4 = 〈1;a〉 if (〈0;let X#4〉 == _|_(explicit error (_|_ literal) in source)) {} x: { y: "" } } } } listCycleOK: { a: 〈0;b〉 b: and([ 〈1;c〉, ]) c: 〈0;a〉 } disjunctionCycle: { a: 〈0;b〉 b: and((1|〈0;c〉)) c: 〈0;a〉 } forCycle: { #A: { a: 〈1;#B〉 } #B: or([ for _, x in 〈1;#A〉 { b: 〈1;x〉 }, ]) } letCycleWithAnd: { a: { d: 〈1;b〉 } b: and([ for _, x in 〈1;a〉 let y = 〈0;x〉 { 〈1;y〉 }, ]) c: 〈0;a〉 } closeCycle: { a: 〈0;b〉 b: close({ d: 〈1;c〉 }) c: 〈0;a〉 } structCycle: { a: 〈0;b〉 b: and([ { d: 〈2;c〉 }, ]) c: 〈0;a〉 } embedCycle: { a: 〈0;b〉 b: close({ 〈1;c〉 }) c: 〈0;a〉 } listAddCycle: { a: 〈0;b〉 b: 〈import;list〉.Concat([ [ 〈2;c〉, ], [ 〈2;c〉, ], ]) c: 〈0;a〉 } listMulCycle: { a: 〈0;b〉 b: 〈import;list〉.Repeat([ { a: { b: 〈3;c〉 } }, ], 3) c: 〈0;a〉 } closeFail: { #T: { [_]: _ } #T: close({ a: string }) x: 〈0;#T〉 x: { b: "foo" } } printCycle: { a: { X: 〈1;a〉 if 〈0;X〉 {} } } } cue-lang-cue-db9cc73/cue/testdata/cycle/expression.txtar000066400000000000000000000072711474664451600234560ustar00rootroot00000000000000-- in.cue -- t1: a: { a1: a0 + 2 b1: a1 - 2 a0: X X: b1 X: 5.0 } t1: b: { X: 5.0 a1: a0 + 2 b1: a1 - 2 a0: X X: b1 } t1: c: { a1: a0 + 2 b1: a1 - 2 X: 5.0 a0: X X: b1 } t1: c: { b1: a1 - 2 a1: a0 + 2 X: 5.0 a0: X X: b1 } t1: c: { b1: a1 - 2 X: 5.0 a1: a0 + 2 a0: X X: b1 } t1total: { for _, v in t1 {v} } // Issue #622 t2: a: { a0: X a1: a0 * 2 Y: a1 b0: Y b1: b0 / 2 X: b1 X: 5.0 } t2: b: { b0: Y b1: b0 / 2 X: b1 a0: X a1: a0 * 2 Y: a1 X: 5.0 } t2: c: { b0: Y b1: b0 / 2 X: b1 X: 5.0 a0: X a1: a0 * 2 Y: a1 } t2: d: { b0: Y b1: b0 / 2 X: b1 a0: X a1: a0 * 2 Y: a1 X: 5.0 } t2total: { for _, v in t2 {v} } -- out/eval/stats -- Leaks: 0 Freed: 58 Reused: 49 Allocs: 9 Retain: 71 Unifications: 58 Conjuncts: 410 Disjuncts: 75 -- out/eval -- (struct){ t1: (struct){ a: (struct){ a1: (float){ 7.0 } b1: (float){ 5.0 } a0: (float){ 5.0 } X: (float){ 5.0 } } b: (struct){ X: (float){ 5.0 } a1: (float){ 7.0 } b1: (float){ 5.0 } a0: (float){ 5.0 } } c: (struct){ a1: (float){ 7.0 } b1: (float){ 5.0 } X: (float){ 5.0 } a0: (float){ 5.0 } } } t1total: (struct){ a1: (float){ 7.0 } b1: (float){ 5.0 } a0: (float){ 5.0 } X: (float){ 5.0 } } t2: (struct){ a: (struct){ a0: (float){ 5.0 } a1: (float){ 10.0 } Y: (float){ 10.0 } b0: (float){ 10.0 } b1: (float){ 5.0 } X: (float){ 5.0 } } b: (struct){ b0: (float){ 10.0 } b1: (float){ 5.0 } X: (float){ 5.0 } a0: (float){ 5.0 } a1: (float){ 10.0 } Y: (float){ 10.0 } } c: (struct){ b0: (float){ 10.0 } b1: (float){ 5.0 } X: (float){ 5.0 } a0: (float){ 5.0 } a1: (float){ 10.0 } Y: (float){ 10.0 } } d: (struct){ b0: (float){ 10.0 } b1: (float){ 5.0 } X: (float){ 5.0 } a0: (float){ 5.0 } a1: (float){ 10.0 } Y: (float){ 10.0 } } } t2total: (struct){ a0: (float){ 5.0 } a1: (float){ 10.0 } Y: (float){ 10.0 } b0: (float){ 10.0 } b1: (float){ 5.0 } X: (float){ 5.0 } } } -- out/compile -- --- in.cue { t1: { a: { a1: (〈0;a0〉 + 2) b1: (〈0;a1〉 - 2) a0: 〈0;X〉 X: 〈0;b1〉 X: 5.0 } } t1: { b: { X: 5.0 a1: (〈0;a0〉 + 2) b1: (〈0;a1〉 - 2) a0: 〈0;X〉 X: 〈0;b1〉 } } t1: { c: { a1: (〈0;a0〉 + 2) b1: (〈0;a1〉 - 2) X: 5.0 a0: 〈0;X〉 X: 〈0;b1〉 } } t1: { c: { b1: (〈0;a1〉 - 2) a1: (〈0;a0〉 + 2) X: 5.0 a0: 〈0;X〉 X: 〈0;b1〉 } } t1: { c: { b1: (〈0;a1〉 - 2) X: 5.0 a1: (〈0;a0〉 + 2) a0: 〈0;X〉 X: 〈0;b1〉 } } t1total: { for _, v in 〈1;t1〉 { 〈1;v〉 } } t2: { a: { a0: 〈0;X〉 a1: (〈0;a0〉 * 2) Y: 〈0;a1〉 b0: 〈0;Y〉 b1: (〈0;b0〉 / 2) X: 〈0;b1〉 X: 5.0 } } t2: { b: { b0: 〈0;Y〉 b1: (〈0;b0〉 / 2) X: 〈0;b1〉 a0: 〈0;X〉 a1: (〈0;a0〉 * 2) Y: 〈0;a1〉 X: 5.0 } } t2: { c: { b0: 〈0;Y〉 b1: (〈0;b0〉 / 2) X: 〈0;b1〉 X: 5.0 a0: 〈0;X〉 a1: (〈0;a0〉 * 2) Y: 〈0;a1〉 } } t2: { d: { b0: 〈0;Y〉 b1: (〈0;b0〉 / 2) X: 〈0;b1〉 a0: 〈0;X〉 a1: (〈0;a0〉 * 2) Y: 〈0;a1〉 X: 5.0 } } t2total: { for _, v in 〈1;t2〉 { 〈1;v〉 } } } cue-lang-cue-db9cc73/cue/testdata/cycle/freeze.txtar000066400000000000000000000443571474664451600225450ustar00rootroot00000000000000// This files tests that values are properly "frozen" in case of mutual // references. Non-structural cyclic references are okay, as long a property // that is dependended upon in the cycle is not changed after the fact, // that is, a value may not become more specific after it is used. -- in.cue -- freezing: t1: ok: { #a: x: "a" len(#a) // 1 } -- comprehension.cue -- // This should be an incomplete error, as z is inserted in x, over which the // comprehension loops. Adding a field z to x would fix this. // This test would fail in the old evaluator, depending on ordering. comprehension: t1: _ comprehension: t1: ok: p0: { x: y: {} // order of comprehensions matter in old evaluator. for _ in x { if true { x: z: a: {} } } if true { if true { x: z: a: {} } } } comprehension: t1: ok: p1: { for _ in x { if true { x: z: a: {} } } x: y: {} if true { if true { x: z: a: {} } } } comprehension: t1: ok: p2: { for _ in x { if true { x: z: a: {} } } if true { if true { x: z: a: {} } } x: y: {} } comprehension: t1: ok: p3: { x: y: {} if true { if true { x: z: a: {} } } for _ in x { if true { x: z: a: {} } } } comprehension: t1: ok: p4: { if true { if true { x: z: a: {} } } x: y: {} for _ in x { if true { x: z: a: {} } } } comprehension: t1: ok: p5: { if true { if true { x: z: a: {} } } for _ in x { if true { x: z: a: {} } } x: y: {} } comprehension: t2: err: { a: { x: 1 for k, v in a { (k+"q"): v // This increases the set of fields in a. } } } comprehension: t3: err: { // mutual dependencies not okay in this case, as the set of fields grows. a: x: 1 b: y: 1 a: { for k, v in b { (k+"q"): v } } b: { for k, v in a { (k): v } } } comprehension: t4: ok: { // It is okay to make x more specific as long as no fields are added. x: y: {} for _ in x { if true { x: y: a: {} } } } comprehension: moreSpecific: ok: { a: { x: int for k, v in a { (k): 1 } } } comprehension: moreSpecific: err: { a: { x: {y: 1} // len(v) should free the size of x. for k, v in a if len(v) > 0 { (k): {z: 1} } } } -- issue3178.cue -- issue3178: { // This should pass. Reasoning: // - second comprehension runs // - in order to satisfy, first comprehension must run // - first comprehension runs and completes input: [ "Value" ] output: {...} for name in input { output: "\(name)": true } for name, v in output { } } -- out/eval/stats -- Leaks: 0 Freed: 72 Reused: 64 Allocs: 8 Retain: 15 Unifications: 72 Conjuncts: 127 Disjuncts: 83 -- out/evalalpha -- Errors: comprehension.t2.err.a: adding field xq not allowed as field set was already referenced: ./comprehension.cue:71:13 comprehension.t3.err.a: adding field xq not allowed as field set was already referenced: ./comprehension.cue:82:13 comprehension.moreSpecific.err.a.x: adding field z not allowed as field set was already referenced: ./comprehension.cue:114:9 Result: (_|_){ // [eval] comprehension: (_|_){ // [eval] t1: (struct){ ok: (struct){ p0: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p1: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p2: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p3: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p4: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p5: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } } } t2: (_|_){ // [eval] err: (_|_){ // [eval] a: (_|_){ // [eval] comprehension.t2.err.a: adding field xq not allowed as field set was already referenced: // ./comprehension.cue:71:13 x: (int){ 1 } } } } t3: (_|_){ // [eval] err: (_|_){ // [eval] a: (_|_){ // [eval] comprehension.t3.err.a: adding field xq not allowed as field set was already referenced: // ./comprehension.cue:82:13 x: (int){ 1 } } b: (struct){ y: (int){ 1 } x: (int){ 1 } } } } t4: (struct){ ok: (struct){ x: (struct){ y: (struct){ a: (struct){ } } } } } moreSpecific: (_|_){ // [eval] ok: (struct){ a: (struct){ x: (int){ 1 } } } err: (_|_){ // [eval] a: (_|_){ // [eval] comprehension.moreSpecific.err.a.x: adding field z not allowed as field set was already referenced: // ./comprehension.cue:114:9 x: (struct){ y: (int){ 1 } } } } } } freezing: (struct){ t1: (struct){ ok: (int){ 1 #a: (#struct){ x: (string){ "a" } } } } } issue3178: (struct){ input: (#list){ 0: (string){ "Value" } } output: (struct){ Value: (bool){ true } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,11 +1,10 @@ Errors: -comprehension.moreSpecific.err.a: field z not allowed by earlier comprehension or reference cycle -comprehension.t1.ok.p0.x: field z not allowed by earlier comprehension or reference cycle -comprehension.t1.ok.p1.x: field z not allowed by earlier comprehension or reference cycle -comprehension.t1.ok.p2.x: field z not allowed by earlier comprehension or reference cycle -comprehension.t2.err.a: field xq not allowed by earlier comprehension or reference cycle -comprehension.t3.err.b: field x not allowed by earlier comprehension or reference cycle -comprehension.t3.err.b: field yq not allowed by earlier comprehension or reference cycle +comprehension.t2.err.a: adding field xq not allowed as field set was already referenced: + ./comprehension.cue:71:13 +comprehension.t3.err.a: adding field xq not allowed as field set was already referenced: + ./comprehension.cue:82:13 +comprehension.moreSpecific.err.a.x: adding field z not allowed as field set was already referenced: + ./comprehension.cue:114:9 Result: (_|_){ @@ -12,38 +11,30 @@ // [eval] comprehension: (_|_){ // [eval] - t1: (_|_){ - // [eval] - ok: (_|_){ - // [eval] - p0: (_|_){ - // [eval] - x: (_|_){ - // [eval] comprehension.t1.ok.p0.x: field z not allowed by earlier comprehension or reference cycle - y: (struct){ - } - z: (struct){ - a: (struct){ - } - } - } - } - p1: (_|_){ - // [eval] - x: (_|_){ - // [eval] comprehension.t1.ok.p1.x: field z not allowed by earlier comprehension or reference cycle - y: (struct){ - } - z: (struct){ - a: (struct){ - } - } - } - } - p2: (_|_){ - // [eval] - x: (_|_){ - // [eval] comprehension.t1.ok.p2.x: field z not allowed by earlier comprehension or reference cycle + t1: (struct){ + ok: (struct){ + p0: (struct){ + x: (struct){ + y: (struct){ + } + z: (struct){ + a: (struct){ + } + } + } + } + p1: (struct){ + x: (struct){ + y: (struct){ + } + z: (struct){ + a: (struct){ + } + } + } + } + p2: (struct){ + x: (struct){ y: (struct){ } z: (struct){ @@ -89,9 +80,9 @@ err: (_|_){ // [eval] a: (_|_){ - // [eval] comprehension.t2.err.a: field xq not allowed by earlier comprehension or reference cycle - x: (int){ 1 } - xq: (int){ 1 } + // [eval] comprehension.t2.err.a: adding field xq not allowed as field set was already referenced: + // ./comprehension.cue:71:13 + x: (int){ 1 } } } } @@ -99,16 +90,14 @@ // [eval] err: (_|_){ // [eval] - a: (struct){ - x: (int){ 1 } - yq: (int){ 1 } - } - b: (_|_){ - // [eval] comprehension.t3.err.b: field x not allowed by earlier comprehension or reference cycle - // comprehension.t3.err.b: field yq not allowed by earlier comprehension or reference cycle + a: (_|_){ + // [eval] comprehension.t3.err.a: adding field xq not allowed as field set was already referenced: + // ./comprehension.cue:82:13 + x: (int){ 1 } + } + b: (struct){ y: (int){ 1 } x: (int){ 1 } - yq: (int){ 1 } } } } @@ -132,10 +121,10 @@ err: (_|_){ // [eval] a: (_|_){ - // [eval] comprehension.moreSpecific.err.a: field z not allowed by earlier comprehension or reference cycle + // [eval] comprehension.moreSpecific.err.a.x: adding field z not allowed as field set was already referenced: + // ./comprehension.cue:114:9 x: (struct){ y: (int){ 1 } - z: (int){ 1 } } } } -- diff/explanation -- v0.7 fixes bugs in v0.6: - comprehension.t1 should be at most an incomplete error, as it is fixable. Arguably they should pass, though, as there is a predictable path to its resolution. -- out/eval -- Errors: comprehension.moreSpecific.err.a: field z not allowed by earlier comprehension or reference cycle comprehension.t1.ok.p0.x: field z not allowed by earlier comprehension or reference cycle comprehension.t1.ok.p1.x: field z not allowed by earlier comprehension or reference cycle comprehension.t1.ok.p2.x: field z not allowed by earlier comprehension or reference cycle comprehension.t2.err.a: field xq not allowed by earlier comprehension or reference cycle comprehension.t3.err.b: field x not allowed by earlier comprehension or reference cycle comprehension.t3.err.b: field yq not allowed by earlier comprehension or reference cycle Result: (_|_){ // [eval] comprehension: (_|_){ // [eval] t1: (_|_){ // [eval] ok: (_|_){ // [eval] p0: (_|_){ // [eval] x: (_|_){ // [eval] comprehension.t1.ok.p0.x: field z not allowed by earlier comprehension or reference cycle y: (struct){ } z: (struct){ a: (struct){ } } } } p1: (_|_){ // [eval] x: (_|_){ // [eval] comprehension.t1.ok.p1.x: field z not allowed by earlier comprehension or reference cycle y: (struct){ } z: (struct){ a: (struct){ } } } } p2: (_|_){ // [eval] x: (_|_){ // [eval] comprehension.t1.ok.p2.x: field z not allowed by earlier comprehension or reference cycle y: (struct){ } z: (struct){ a: (struct){ } } } } p3: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p4: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } p5: (struct){ x: (struct){ y: (struct){ } z: (struct){ a: (struct){ } } } } } } t2: (_|_){ // [eval] err: (_|_){ // [eval] a: (_|_){ // [eval] comprehension.t2.err.a: field xq not allowed by earlier comprehension or reference cycle x: (int){ 1 } xq: (int){ 1 } } } } t3: (_|_){ // [eval] err: (_|_){ // [eval] a: (struct){ x: (int){ 1 } yq: (int){ 1 } } b: (_|_){ // [eval] comprehension.t3.err.b: field x not allowed by earlier comprehension or reference cycle // comprehension.t3.err.b: field yq not allowed by earlier comprehension or reference cycle y: (int){ 1 } x: (int){ 1 } yq: (int){ 1 } } } } t4: (struct){ ok: (struct){ x: (struct){ y: (struct){ a: (struct){ } } } } } moreSpecific: (_|_){ // [eval] ok: (struct){ a: (struct){ x: (int){ 1 } } } err: (_|_){ // [eval] a: (_|_){ // [eval] comprehension.moreSpecific.err.a: field z not allowed by earlier comprehension or reference cycle x: (struct){ y: (int){ 1 } z: (int){ 1 } } } } } } freezing: (struct){ t1: (struct){ ok: (int){ 1 #a: (#struct){ x: (string){ "a" } } } } } issue3178: (struct){ input: (#list){ 0: (string){ "Value" } } output: (struct){ Value: (bool){ true } } } } -- out/compile -- --- comprehension.cue { comprehension: { t1: _ } comprehension: { t1: { ok: { p0: { x: { y: {} } for _, _ in 〈0;x〉 { if true { x: { z: { a: {} } } } } if true { if true { x: { z: { a: {} } } } } } } } } comprehension: { t1: { ok: { p1: { for _, _ in 〈0;x〉 { if true { x: { z: { a: {} } } } } x: { y: {} } if true { if true { x: { z: { a: {} } } } } } } } } comprehension: { t1: { ok: { p2: { for _, _ in 〈0;x〉 { if true { x: { z: { a: {} } } } } if true { if true { x: { z: { a: {} } } } } x: { y: {} } } } } } comprehension: { t1: { ok: { p3: { x: { y: {} } if true { if true { x: { z: { a: {} } } } } for _, _ in 〈0;x〉 { if true { x: { z: { a: {} } } } } } } } } comprehension: { t1: { ok: { p4: { if true { if true { x: { z: { a: {} } } } } x: { y: {} } for _, _ in 〈0;x〉 { if true { x: { z: { a: {} } } } } } } } } comprehension: { t1: { ok: { p5: { if true { if true { x: { z: { a: {} } } } } for _, _ in 〈0;x〉 { if true { x: { z: { a: {} } } } } x: { y: {} } } } } } comprehension: { t2: { err: { a: { x: 1 for k, v in 〈1;a〉 { (〈1;k〉 + "q"): 〈1;v〉 } } } } } comprehension: { t3: { err: { a: { x: 1 } b: { y: 1 } a: { for k, v in 〈1;b〉 { (〈1;k〉 + "q"): 〈1;v〉 } } b: { for k, v in 〈1;a〉 { 〈1;k〉: 〈1;v〉 } } } } } comprehension: { t4: { ok: { x: { y: {} } for _, _ in 〈0;x〉 { if true { x: { y: { a: {} } } } } } } } comprehension: { moreSpecific: { ok: { a: { x: int for k, v in 〈1;a〉 { 〈1;k〉: 1 } } } } } comprehension: { moreSpecific: { err: { a: { x: { y: 1 } for k, v in 〈1;a〉 if (len(〈0;v〉) > 0) { 〈1;k〉: { z: 1 } } } } } } } --- in.cue { freezing: { t1: { ok: { #a: { x: "a" } len(〈0;#a〉) } } } } --- issue3178.cue { issue3178: { input: [ "Value", ] output: { ... } for _, name in 〈0;input〉 { output: { "\(〈2;name〉)": true } } for name, v in 〈0;output〉 {} } } cue-lang-cue-db9cc73/cue/testdata/cycle/inline.txtar000066400000000000000000000206721474664451600225350ustar00rootroot00000000000000-- x.cue -- // variants of fib inline: small: { f: { n: int out: (f & {"n": n - 1}).out } } inline: medium: { f2: (f & {n: 2}).out fRec: {nn: int, out: (f & {n: nn}).out} f: { n: int out: (fRec & {nn: n - 1}).out } } inline: patterns: { f: n: (f & {n: {}}).n f: n: {} [string]: {n: {}} f: [string]: {} f: {} } inline: acrossFields: fail1: { f: { in: number out: in + 1 } k00: 0 k10: (f & {in: k00}).out k20: (f & {in: k10}).out k30: (f & {in: k20}).out // invalid recursion is here. k10: (f & {in: k30}).out } // Issue #2163 inline: acrossFields: ok1: { f: { in: number out: in } k00: 0 k10: (f & {in: k00}).out k20: (f & {in: k10}).out k30: (f & {in: k20}).out // TODO: what is correct behavior here. // This is borderline okay. k10: (f & {in: k30}).out } -- out/compile -- --- x.cue { inline: { small: { f: { n: int out: (〈1;f〉 & { n: (〈1;n〉 - 1) }).out } } } inline: { medium: { f2: (〈0;f〉 & { n: 2 }).out fRec: { nn: int out: (〈1;f〉 & { n: 〈1;nn〉 }).out } f: { n: int out: (〈1;fRec〉 & { nn: (〈1;n〉 - 1) }).out } } } inline: { patterns: { f: { n: (〈1;f〉 & { n: {} }).n } f: { n: {} } [string]: { n: {} } f: { [string]: {} } f: {} } } inline: { acrossFields: { fail1: { f: { in: number out: (〈0;in〉 + 1) } k00: 0 k10: (〈0;f〉 & { in: 〈1;k00〉 }).out k20: (〈0;f〉 & { in: 〈1;k10〉 }).out k30: (〈0;f〉 & { in: 〈1;k20〉 }).out k10: (〈0;f〉 & { in: 〈1;k30〉 }).out } } } inline: { acrossFields: { ok1: { f: { in: number out: 〈0;in〉 } k00: 0 k10: (〈0;f〉 & { in: 〈1;k00〉 }).out k20: (〈0;f〉 & { in: 〈1;k10〉 }).out k30: (〈0;f〉 & { in: 〈1;k20〉 }).out k10: (〈0;f〉 & { in: 〈1;k30〉 }).out } } } } -- out/evalalpha/stats -- Leaks: 148 Freed: 0 Reused: 0 Allocs: 148 Retain: 0 Unifications: 108 Conjuncts: 552 Disjuncts: 0 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 247 -Freed: 141 -Reused: 136 -Allocs: 252 -Retain: 834 +Leaks: 148 +Freed: 0 +Reused: 0 +Allocs: 148 +Retain: 0 -Unifications: 388 -Conjuncts: 1307 -Disjuncts: 707 +Unifications: 108 +Conjuncts: 552 +Disjuncts: 0 -- out/eval/stats -- Leaks: 247 Freed: 141 Reused: 136 Allocs: 252 Retain: 834 Unifications: 388 Conjuncts: 1307 Disjuncts: 707 -- out/eval -- Errors: structural cycle: ./x.cue:6:9 structural cycle: ./x.cue:15:9 structural cycle: ./x.cue:20:9 in: structural cycle: ./x.cue:30:8 Result: (_|_){ // [structural cycle] inline: (_|_){ // [structural cycle] small: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] n: (int){ int } out: (_|_){ // [structural cycle] structural cycle: // ./x.cue:6:9 } } } medium: (_|_){ // [structural cycle] f2: (_|_){ // [structural cycle] structural cycle: // ./x.cue:15:9 } fRec: (_|_){ // [structural cycle] nn: (int){ int } out: (_|_){ // [structural cycle] structural cycle: // ./x.cue:15:9 } } f: (_|_){ // [structural cycle] n: (int){ int } out: (_|_){ // [structural cycle] structural cycle: // ./x.cue:15:9 } } } patterns: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] n: (_|_){ // [structural cycle] structural cycle: // ./x.cue:20:9 } } } acrossFields: (_|_){ // [structural cycle] fail1: (_|_){ // [structural cycle] f: (struct){ in: (number){ number } out: (_|_){ // [incomplete] inline.acrossFields.fail1.f.out: non-concrete value number in operand to +: // ./x.cue:30:8 // ./x.cue:29:8 } } k00: (int){ 0 } k10: (_|_){ // [structural cycle] in: structural cycle: // ./x.cue:30:8 } k20: (_|_){ // [structural cycle] in: structural cycle: // ./x.cue:30:8 } k30: (_|_){ // [structural cycle] in: structural cycle: // ./x.cue:30:8 } } ok1: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } } } } -- out/evalalpha -- Errors: structural cycle: ./x.cue:6:9 structural cycle: ./x.cue:12:24 structural cycle: ./x.cue:15:9 structural cycle: ./x.cue:20:9 in: structural cycle: ./x.cue:38:17 Result: (_|_){ // [structural cycle] inline: (_|_){ // [structural cycle] small: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] n: (int){ int } out: (_|_){ // [structural cycle] structural cycle: // ./x.cue:6:9 } } } medium: (_|_){ // [structural cycle] f2: (_|_){ // [structural cycle] structural cycle: // ./x.cue:12:24 } fRec: (_|_){ // [structural cycle] nn: (int){ int } out: (_|_){ // [structural cycle] structural cycle: // ./x.cue:15:9 } } f: (_|_){ // [structural cycle] n: (int){ int } out: (_|_){ // [structural cycle] structural cycle: // ./x.cue:15:9 } } } patterns: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] n: (_|_){ // [structural cycle] structural cycle: // ./x.cue:20:9 } } } acrossFields: (_|_){ // [structural cycle] fail1: (_|_){ // [structural cycle] f: (struct){ in: (number){ number } out: (_|_){ // [incomplete] inline.acrossFields.fail1.f.out: non-concrete value number in operand to +: // ./x.cue:30:8 // ./x.cue:29:8 } } k00: (int){ 0 } k10: (_|_){ // [structural cycle] in: structural cycle: // ./x.cue:38:17 } k20: (_|_){ // [structural cycle] in: structural cycle: // ./x.cue:38:17 } k30: (_|_){ // [structural cycle] in: structural cycle: // ./x.cue:38:17 } } ok1: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,11 +2,13 @@ structural cycle: ./x.cue:6:9 structural cycle: + ./x.cue:12:24 +structural cycle: ./x.cue:15:9 structural cycle: ./x.cue:20:9 in: structural cycle: - ./x.cue:30:8 + ./x.cue:38:17 Result: (_|_){ @@ -28,7 +30,7 @@ // [structural cycle] f2: (_|_){ // [structural cycle] structural cycle: - // ./x.cue:15:9 + // ./x.cue:12:24 } fRec: (_|_){ // [structural cycle] @@ -72,15 +74,15 @@ k00: (int){ 0 } k10: (_|_){ // [structural cycle] in: structural cycle: - // ./x.cue:30:8 + // ./x.cue:38:17 } k20: (_|_){ // [structural cycle] in: structural cycle: - // ./x.cue:30:8 + // ./x.cue:38:17 } k30: (_|_){ // [structural cycle] in: structural cycle: - // ./x.cue:30:8 + // ./x.cue:38:17 } } ok1: (struct){ -- diff/todo/p2 -- One test now fails. Given TODO, this may be okay. This does break Issue #2163. cue-lang-cue-db9cc73/cue/testdata/cycle/inline_non_recursive.txtar000066400000000000000000000251201474664451600254670ustar00rootroot00000000000000-- in.cue -- // All these should pass. These look like recursive inlined calls, but they are // not. ok1: { f: { in: number out: in } k00: 0 k10: (f & {in: k00}).out k20: (f & {in: k10}).out k30: (f & {in: k20}).out } ok2: { f: { in: number out: in } k00: 0 k10: {(f & {in: k00}).out} k20: {(f & {in: k10}).out} k30: {(f & {in: k20}).out} } ok3: { f: { in: number out: in } k00: 0 k10: {close((f & {in: k00})).out} k20: {close((f & {in: k10})).out} k30: {close((f & {in: k20})).out} } ok4: { f: { in: number out: in } k00: 0 k10: {out: {(f & {in: k00}).out}}.out k20: {out: {(f & {in: k10}).out}}.out k30: {out: {(f & {in: k20}).out}}.out } // Issue #1708 issue1708: { #add10: { in: number a10: { i: in, o: i + 10 } out: a10.o } k00: 0 k10: (#add10 & {in: k00}).out k20: (#add10 & {in: k10}).out k30: (#add10 & {in: k20}).out } -- issue3182.cue -- issue3182: { first: t1: { x: { a: x }.a } first: t2: { x: { a: b: x }.a } second: { { t: x }.t.y x: y: x: y: a: 1 } third: { { p: { x: p y: 1 } }.p.x.y } } -- select.cue -- // The value of #Step should be consistent between these test cases. select: direct: { #Step: (#Job & {opt: _}).opt #Job: matchN(1, [#NormalJob]) } select: indirect: { #Step: #Job.opt #Job: matchN(1, [#NormalJob]) & {opt: _} } #NormalJob: { req!: int opt?: run?: string } -- out/evalalpha/stats -- Leaks: 228 Freed: 0 Reused: 0 Allocs: 228 Retain: 0 Unifications: 183 Conjuncts: 824 Disjuncts: 0 -- out/evalalpha -- Errors: issue3182.first.t2.x.b: structural cycle Result: (_|_){ // [structural cycle] ok1: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } ok2: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } ok3: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } ok4: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } issue1708: (struct){ #add10: (#struct){ in: (number){ number } a10: (#struct){ i: (number){ number } o: (_|_){ // [incomplete] issue1708.#add10.a10.o: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 } } out: (_|_){ // [incomplete] issue1708.#add10.a10.o: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 } } k00: (int){ 0 } k10: (int){ 10 } k20: (int){ 20 } k30: (int){ 30 } } issue3182: (_|_){ // [structural cycle] first: (_|_){ // [structural cycle] t1: (struct){ x: (_){ _ } } t2: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] issue3182.first.t2.x.b: structural cycle } } } } second: (struct){ x: (struct){ y: (struct){ x: (struct){ y: (struct){ a: (int){ 1 } } } a: (int){ 1 } } } a: (int){ 1 } } third: (int){ 1 } } select: (struct){ direct: (struct){ #Step: (_){ _ } #Job: (_){ matchN(1, (#list){ 0: (_|_){// &[〈3;#NormalJob〉] } }) } } indirect: (struct){ #Step: (_){ _ } #Job: (_|_){ // [incomplete] select.indirect.#Job: invalid value {opt:_} (does not satisfy matchN): 0 matched, expected 1: // ./select.cue:8:8 // ./select.cue:8:15 opt: (_){ _ } } } } #NormalJob: (#struct){ req!: (int){ int } opt?: (#struct){ run?: (string){ string } } } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 309 -Freed: 437 -Reused: 429 -Allocs: 317 -Retain: 1074 +Leaks: 228 +Freed: 0 +Reused: 0 +Allocs: 228 +Retain: 0 -Unifications: 746 -Conjuncts: 2813 -Disjuncts: 1485 +Unifications: 183 +Conjuncts: 824 +Disjuncts: 0 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -53,14 +53,12 @@ // [incomplete] issue1708.#add10.a10.o: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 - // ./in.cue:52:13 } } out: (_|_){ - // [incomplete] issue1708.#add10.out: non-concrete value number in operand to +: + // [incomplete] issue1708.#add10.a10.o: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 - // ./in.cue:52:13 } } k00: (int){ 0 } @@ -104,7 +102,7 @@ direct: (struct){ #Step: (_){ _ } #Job: (_){ matchN(1, (#list){ - 0: (_|_){// 〈3;#NormalJob〉 + 0: (_|_){// &[〈3;#NormalJob〉] } }) } } -- diff/todo/p3 -- Error positions. Incorrect path due to structure sharing. -- out/eval/stats -- Leaks: 309 Freed: 437 Reused: 429 Allocs: 317 Retain: 1074 Unifications: 746 Conjuncts: 2813 Disjuncts: 1485 -- out/eval -- Errors: issue3182.first.t2.x.b: structural cycle Result: (_|_){ // [structural cycle] ok1: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } ok2: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } ok3: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } ok4: (struct){ f: (struct){ in: (number){ number } out: (number){ number } } k00: (int){ 0 } k10: (int){ 0 } k20: (int){ 0 } k30: (int){ 0 } } issue1708: (struct){ #add10: (#struct){ in: (number){ number } a10: (#struct){ i: (number){ number } o: (_|_){ // [incomplete] issue1708.#add10.a10.o: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 // ./in.cue:52:13 } } out: (_|_){ // [incomplete] issue1708.#add10.out: non-concrete value number in operand to +: // ./in.cue:52:20 // ./in.cue:51:7 // ./in.cue:52:13 } } k00: (int){ 0 } k10: (int){ 10 } k20: (int){ 20 } k30: (int){ 30 } } issue3182: (_|_){ // [structural cycle] first: (_|_){ // [structural cycle] t1: (struct){ x: (_){ _ } } t2: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] issue3182.first.t2.x.b: structural cycle } } } } second: (struct){ x: (struct){ y: (struct){ x: (struct){ y: (struct){ a: (int){ 1 } } } a: (int){ 1 } } } a: (int){ 1 } } third: (int){ 1 } } select: (struct){ direct: (struct){ #Step: (_){ _ } #Job: (_){ matchN(1, (#list){ 0: (_|_){// 〈3;#NormalJob〉 } }) } } indirect: (struct){ #Step: (_){ _ } #Job: (_|_){ // [incomplete] select.indirect.#Job: invalid value {opt:_} (does not satisfy matchN): 0 matched, expected 1: // ./select.cue:8:8 // ./select.cue:8:15 opt: (_){ _ } } } } #NormalJob: (#struct){ req!: (int){ int } opt?: (#struct){ run?: (string){ string } } } } -- out/compile -- --- in.cue { ok1: { f: { in: number out: 〈0;in〉 } k00: 0 k10: (〈0;f〉 & { in: 〈1;k00〉 }).out k20: (〈0;f〉 & { in: 〈1;k10〉 }).out k30: (〈0;f〉 & { in: 〈1;k20〉 }).out } ok2: { f: { in: number out: 〈0;in〉 } k00: 0 k10: { (〈1;f〉 & { in: 〈2;k00〉 }).out } k20: { (〈1;f〉 & { in: 〈2;k10〉 }).out } k30: { (〈1;f〉 & { in: 〈2;k20〉 }).out } } ok3: { f: { in: number out: 〈0;in〉 } k00: 0 k10: { close((〈1;f〉 & { in: 〈2;k00〉 })).out } k20: { close((〈1;f〉 & { in: 〈2;k10〉 })).out } k30: { close((〈1;f〉 & { in: 〈2;k20〉 })).out } } ok4: { f: { in: number out: 〈0;in〉 } k00: 0 k10: { out: { (〈2;f〉 & { in: 〈3;k00〉 }).out } }.out k20: { out: { (〈2;f〉 & { in: 〈3;k10〉 }).out } }.out k30: { out: { (〈2;f〉 & { in: 〈3;k20〉 }).out } }.out } issue1708: { #add10: { in: number a10: { i: 〈1;in〉 o: (〈0;i〉 + 10) } out: 〈0;a10〉.o } k00: 0 k10: (〈0;#add10〉 & { in: 〈1;k00〉 }).out k20: (〈0;#add10〉 & { in: 〈1;k10〉 }).out k30: (〈0;#add10〉 & { in: 〈1;k20〉 }).out } } --- issue3182.cue { issue3182: { first: { t1: { x: { a: 〈1;x〉 }.a } } first: { t2: { x: { a: { b: 〈2;x〉 } }.a } } second: { { t: 〈1;x〉 }.t.y x: { y: { x: { y: { a: 1 } } } } } third: { { p: { x: 〈1;p〉 y: 1 } }.p.x.y } } } --- select.cue { select: { direct: { #Step: (〈0;#Job〉 & { opt: _ }).opt #Job: matchN(1, [ 〈3;#NormalJob〉, ]) } } select: { indirect: { #Step: 〈0;#Job〉.opt #Job: (matchN(1, [ 〈3;#NormalJob〉, ]) & { opt: _ }) } } #NormalJob: { req!: int opt?: { run?: string } } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue1960.txtar000066400000000000000000000045771474664451600227350ustar00rootroot00000000000000// Issue-specific tests. Essence tested in evaluate.txtar (LetCycle*). -- issue1960.cue -- t1: { z: blah: s: [for z in z {}] z: hello: { for x in p {} let q = z.blah p: q.r // Incomplete error should not cause cycle. p: t: 1 } } t2: { z: blah: s: [for z in z {}] z: hello: { for x in p {} let q = z.blah p: t: 1 } } t3: { #z: { n: string p: t: "e" s: [...string] _p: { n: string e: p: {} } r: (_p )[p.t] for _, pl in r.p { if pl.blah { } } } #i: { #z t: "i" r: e: {} } #c: { #z t: "c" n: string } z: [N= =~"^b"]: #i & { s: [ for n, z in z if z.t == "c" if z.n == N {n}, ] } z: [N= =~"^h"]: #c & { n: string // Causes a structural cycle on its own, but not when referenced below. let q = z[n] p: q.r.e } z: { "blah": {} "hello": n: "blah" } } -- out/eval -- t2.z.hello: unreferenced alias or let clause q: ./issue1960.cue:15:3 -- out/compile -- t2.z.hello: unreferenced alias or let clause q: ./issue1960.cue:15:3 --- issue1960.cue { t1: { z: { blah: { s: [ for _, z in 〈3;z〉 {}, ] } } z: { hello: { for _, x in 〈0;p〉 {} let q#1 = 〈2;z〉.blah p: 〈0;let q#1〉.r p: { t: 1 } } } } t2: { z: { blah: { s: [ for _, z in 〈3;z〉 {}, ] } } z: { hello: { for _, x in 〈0;p〉 {} let q#2 = 〈2;z〉.blah p: { t: 1 } } } } t3: { #z: { n: string p: { t: "e" } s: [ ...string, ] _p: { n: string e: { p: {} } } r: 〈0;_p〉[〈0;p〉.t] for _, pl in 〈0;r〉.p { if 〈1;pl〉.blah {} } } #i: { 〈1;#z〉 t: "i" r: { e: {} } } #c: { 〈1;#z〉 t: "c" n: string } z: { [=~"^b"]: (〈1;#i〉 & { s: [ for n, z in 〈3;z〉 if (〈0;z〉.t == "c") if (〈0;z〉.n == 〈3;-〉) { 〈1;n〉 }, ] }) } z: { [=~"^h"]: (〈1;#c〉 & { n: string let q#3 = 〈2;z〉[〈0;n〉] p: 〈0;let q#3〉.r.e }) } z: { blah: {} hello: { n: "blah" } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue241.txtar000066400000000000000000000036541474664451600226370ustar00rootroot00000000000000-- in.cue -- #Value: 0 | 1 foo: #Value foo: !=bar bar: #Value bar: !=foo #Value: 0 | 1 Foo: #Value Foo: !=Bar Bar: #Value Bar: !=Foo Bar: 0 cell: a: 0 | 1 cell: a: !=cell.b cell: b: 0 | 1 cell: b: !=cell.a cell: a: 0 cell: b: _ a: cell.a b: cell.b -- out/eval/stats -- Leaks: 0 Freed: 47 Reused: 39 Allocs: 8 Retain: 7 Unifications: 11 Conjuncts: 101 Disjuncts: 47 -- out/evalalpha -- (struct){ #Value: (int){ |((int){ 0 }, (int){ 1 }) } foo: (_|_){ // [cycle] cycle error } bar: (_|_){ // [cycle] cycle error } Foo: (int){ 1 } Bar: (int){ 0 } cell: (struct){ a: (int){ 0 } b: (int){ 1 } } a: (int){ 0 } b: (int){ 1 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,10 +1,11 @@ (struct){ #Value: (int){ |((int){ 0 }, (int){ 1 }) } foo: (_|_){ - // [incomplete] foo: unresolved disjunction 0 | 1 (type int): - // ./in.cue:4:6 - } - bar: (int){ |((int){ 0 }, (int){ 1 }) } + // [cycle] cycle error + } + bar: (_|_){ + // [cycle] cycle error + } Foo: (int){ 1 } Bar: (int){ 0 } cell: (struct){ -- diff/explanation -- error is now symmetric -- out/eval -- (struct){ #Value: (int){ |((int){ 0 }, (int){ 1 }) } foo: (_|_){ // [incomplete] foo: unresolved disjunction 0 | 1 (type int): // ./in.cue:4:6 } bar: (int){ |((int){ 0 }, (int){ 1 }) } Foo: (int){ 1 } Bar: (int){ 0 } cell: (struct){ a: (int){ 0 } b: (int){ 1 } } a: (int){ 0 } b: (int){ 1 } } -- out/compile -- --- in.cue { #Value: (0|1) foo: 〈0;#Value〉 foo: !=〈0;bar〉 bar: 〈0;#Value〉 bar: !=〈0;foo〉 #Value: (0|1) Foo: 〈0;#Value〉 Foo: !=〈0;Bar〉 Bar: 〈0;#Value〉 Bar: !=〈0;Foo〉 Bar: 0 cell: { a: (0|1) } cell: { a: !=〈1;cell〉.b } cell: { b: (0|1) } cell: { b: !=〈1;cell〉.a } cell: { a: 0 } cell: { b: _ } a: 〈0;cell〉.a b: 〈0;cell〉.b } cue-lang-cue-db9cc73/cue/testdata/cycle/issue242.txtar000066400000000000000000000102411474664451600226260ustar00rootroot00000000000000-- in.cue -- #size: 2 #CellValue: 0 | 1 | 2 | 3 cell: "0": "0": #CellValue cell: "0": "0": !=cell["0"]["1"] cell: "0": "0": !=cell["1"]["0"] cell: "0": "0": !=cell["1"]["1"] cell: "0": "1": #CellValue cell: "0": "1": !=cell["0"]["0"] cell: "0": "1": !=cell["1"]["0"] cell: "0": "1": !=cell["1"]["1"] cell: "1": "0": #CellValue cell: "1": "0": !=cell["0"]["0"] cell: "1": "0": !=cell["0"]["1"] cell: "1": "0": !=cell["1"]["1"] cell: "1": "1": #CellValue cell: "1": "1": !=cell["0"]["0"] cell: "1": "1": !=cell["0"]["1"] cell: "1": "1": !=cell["1"]["0"] cell: "0": "0": 0 cell: "0": "1": 1 cell: "1": "0": 2 cell: "1": "1": 3 cell2: a: 0 | 1 cell2: a: !=cell2.b cell2: b: 0 | 1 cell2: b: !=cell2.a cell2: a: _ cell2: b: 1 cell3: a: 0 | 1 cell3: a: !=cell3.b cell3: b: 0 | 1 cell3: b: !=cell3.a cell3: a: 0 cell3: b: _ cell4: a: 0 | 1 cell4: a: !=cell4.b cell4: b: 0 | 1 cell4: b: !=cell4.a cell4: b: _ cell4: a: 0 cell5: b: 0 | 1 cell5: b: !=cell5.a cell5: a: 0 | 1 cell5: a: !=cell5.b cell5: b: _ cell5: a: 0 a: #CellValue a: !=b a: !=c a: !=d b: #CellValue b: !=a b: !=c b: !=d c: #CellValue c: !=a c: !=b c: !=d d: #CellValue d: !=a d: !=b d: !=c a: 0 b: 1 c: 2 d: 3 -- out/eval/stats -- Leaks: 0 Freed: 78 Reused: 68 Allocs: 10 Retain: 18 Unifications: 26 Conjuncts: 181 Disjuncts: 82 -- out/eval -- (struct){ #size: (int){ 2 } #CellValue: (int){ |((int){ 0 }, (int){ 1 }, (int){ 2 }, (int){ 3 }) } cell: (struct){ "0": (struct){ "0": (int){ 0 } "1": (int){ 1 } } "1": (struct){ "0": (int){ 2 } "1": (int){ 3 } } } cell2: (struct){ a: (int){ 0 } b: (int){ 1 } } cell3: (struct){ a: (int){ 0 } b: (int){ 1 } } cell4: (struct){ a: (int){ 0 } b: (int){ 1 } } cell5: (struct){ b: (int){ 1 } a: (int){ 0 } } a: (int){ 0 } b: (int){ 1 } c: (int){ 2 } d: (int){ 3 } } -- out/compile -- --- in.cue { #size: 2 #CellValue: (0|1|2|3) cell: { "0": { "0": 〈2;#CellValue〉 } } cell: { "0": { "0": !=〈2;cell〉["0"]["1"] } } cell: { "0": { "0": !=〈2;cell〉["1"]["0"] } } cell: { "0": { "0": !=〈2;cell〉["1"]["1"] } } cell: { "0": { "1": 〈2;#CellValue〉 } } cell: { "0": { "1": !=〈2;cell〉["0"]["0"] } } cell: { "0": { "1": !=〈2;cell〉["1"]["0"] } } cell: { "0": { "1": !=〈2;cell〉["1"]["1"] } } cell: { "1": { "0": 〈2;#CellValue〉 } } cell: { "1": { "0": !=〈2;cell〉["0"]["0"] } } cell: { "1": { "0": !=〈2;cell〉["0"]["1"] } } cell: { "1": { "0": !=〈2;cell〉["1"]["1"] } } cell: { "1": { "1": 〈2;#CellValue〉 } } cell: { "1": { "1": !=〈2;cell〉["0"]["0"] } } cell: { "1": { "1": !=〈2;cell〉["0"]["1"] } } cell: { "1": { "1": !=〈2;cell〉["1"]["0"] } } cell: { "0": { "0": 0 } } cell: { "0": { "1": 1 } } cell: { "1": { "0": 2 } } cell: { "1": { "1": 3 } } cell2: { a: (0|1) } cell2: { a: !=〈1;cell2〉.b } cell2: { b: (0|1) } cell2: { b: !=〈1;cell2〉.a } cell2: { a: _ } cell2: { b: 1 } cell3: { a: (0|1) } cell3: { a: !=〈1;cell3〉.b } cell3: { b: (0|1) } cell3: { b: !=〈1;cell3〉.a } cell3: { a: 0 } cell3: { b: _ } cell4: { a: (0|1) } cell4: { a: !=〈1;cell4〉.b } cell4: { b: (0|1) } cell4: { b: !=〈1;cell4〉.a } cell4: { b: _ } cell4: { a: 0 } cell5: { b: (0|1) } cell5: { b: !=〈1;cell5〉.a } cell5: { a: (0|1) } cell5: { a: !=〈1;cell5〉.b } cell5: { b: _ } cell5: { a: 0 } a: 〈0;#CellValue〉 a: !=〈0;b〉 a: !=〈0;c〉 a: !=〈0;d〉 b: 〈0;#CellValue〉 b: !=〈0;a〉 b: !=〈0;c〉 b: !=〈0;d〉 c: 〈0;#CellValue〉 c: !=〈0;a〉 c: !=〈0;b〉 c: !=〈0;d〉 d: 〈0;#CellValue〉 d: !=〈0;a〉 d: !=〈0;b〉 d: !=〈0;c〉 a: 0 b: 1 c: 2 d: 3 } cue-lang-cue-db9cc73/cue/testdata/cycle/issue306.txtar000066400000000000000000000012311474664451600226260ustar00rootroot00000000000000-- in.cue -- a: 12 #Controller: settings: { controller: #Controller } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 1 Allocs: 4 Retain: 0 Unifications: 5 Conjuncts: 5 Disjuncts: 5 -- out/eval -- Errors: #Controller.settings.controller: structural cycle Result: (_|_){ // [structural cycle] a: (int){ 12 } #Controller: (_|_){ // [structural cycle] settings: (_|_){ // [structural cycle] controller: (_|_){ // [structural cycle] #Controller.settings.controller: structural cycle } } } } -- out/compile -- --- in.cue { a: 12 #Controller: { settings: { controller: 〈2;#Controller〉 } } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue3118.txtar000066400000000000000000000112761474664451600227240ustar00rootroot00000000000000-- in.cue -- #TimeSpan: { start: float duration: float end: float start: end - duration duration: end - start end: start + duration start: <=end } examples: [string]: #TimeSpan examples: eg1: { start: 10.0 duration: 2.1 } examples: eg2: { start: 10.0 } examples: eg3: { end: 10.0 } -- out/evalalpha/stats -- Leaks: 19 Freed: 0 Reused: 0 Allocs: 19 Retain: 0 Unifications: 19 Conjuncts: 98 Disjuncts: 0 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 18 -Reused: 12 -Allocs: 6 -Retain: 269 +Leaks: 19 +Freed: 0 +Reused: 0 +Allocs: 19 +Retain: 0 -Unifications: 18 -Conjuncts: 354 -Disjuncts: 19 +Unifications: 19 +Conjuncts: 98 +Disjuncts: 0 -- out/eval/stats -- Leaks: 0 Freed: 18 Reused: 12 Allocs: 6 Retain: 269 Unifications: 18 Conjuncts: 354 Disjuncts: 19 -- out/evalalpha -- (struct){ #TimeSpan: (#struct){ start: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 // cycle error: // ./in.cue:8:12 } duration: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } end: (_|_){ // [cycle] cycle error: // ./in.cue:8:12 } } examples: (struct){ eg1: (#struct){ start: (float){ 10.0 } duration: (float){ 2.1 } end: (float){ 12.1 } } eg2: (#struct){ start: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } duration: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } end: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } } eg3: (#struct){ end: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } start: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } duration: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } } } } -- diff/explanation -- the new evaluator includes positions with the cycle error and the old evaluator does not. -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,10 @@ (struct){ #TimeSpan: (#struct){ start: (_|_){ - // [cycle] cycle error + // [cycle] cycle error: + // ./in.cue:7:12 + // cycle error: + // ./in.cue:8:12 } duration: (_|_){ // [cycle] cycle error: @@ -20,26 +23,30 @@ } eg2: (#struct){ start: (_|_){ - // [cycle] cycle error - } - duration: (_|_){ - // [cycle] cycle error: - // ./in.cue:7:12 - } - end: (_|_){ - // [cycle] cycle error + // [cycle] cycle error: + // ./in.cue:7:12 + } + duration: (_|_){ + // [cycle] cycle error: + // ./in.cue:7:12 + } + end: (_|_){ + // [cycle] cycle error: + // ./in.cue:7:12 } } eg3: (#struct){ end: (_|_){ // [cycle] cycle error: - // ./in.cue:8:12 - } - start: (_|_){ - // [cycle] cycle error - } - duration: (_|_){ - // [cycle] cycle error + // ./in.cue:7:12 + } + start: (_|_){ + // [cycle] cycle error: + // ./in.cue:7:12 + } + duration: (_|_){ + // [cycle] cycle error: + // ./in.cue:7:12 } } } -- out/eval -- (struct){ #TimeSpan: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } end: (_|_){ // [cycle] cycle error: // ./in.cue:8:12 } } examples: (struct){ eg1: (#struct){ start: (float){ 10.0 } duration: (float){ 2.1 } end: (float){ 12.1 } } eg2: (#struct){ start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error: // ./in.cue:7:12 } end: (_|_){ // [cycle] cycle error } } eg3: (#struct){ end: (_|_){ // [cycle] cycle error: // ./in.cue:8:12 } start: (_|_){ // [cycle] cycle error } duration: (_|_){ // [cycle] cycle error } } } } -- out/compile -- --- in.cue { #TimeSpan: { start: float duration: float end: float start: (〈0;end〉 - 〈0;duration〉) duration: (〈0;end〉 - 〈0;start〉) end: (〈0;start〉 + 〈0;duration〉) start: <=〈0;end〉 } examples: { [string]: 〈1;#TimeSpan〉 } examples: { eg1: { start: 10.0 duration: 2.1 } } examples: { eg2: { start: 10.0 } } examples: { eg3: { end: 10.0 } } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue3527.txtar000066400000000000000000000102151474664451600227200ustar00rootroot00000000000000// Issue #3527 // This code caused a panic before. -- in.cue -- package p _taxPayer: self: {} let sam = {taxPayer: _taxPayer} assert: { invoke: sam invoke: _ res: subject & {in: invoke} } subject: { in: #ReturnData _computed: (#computeF1040 & {"in": in}) } #computeF1040: in: #ReturnData #ReturnData: taxPayer?: #TaxPayer #TaxPayer: self?: _ -- out/eval/stats -- Leaks: 0 Freed: 35 Reused: 26 Allocs: 9 Retain: 4 Unifications: 35 Conjuncts: 82 Disjuncts: 39 -- out/evalalpha -- (struct){ _taxPayer(:p): (struct){ self: (struct){ } } let sam#1 = (struct){ taxPayer: ~(_taxPayer(:p)) } assert: (struct){ invoke: (struct){ taxPayer: ~(_taxPayer(:p)) } res: (struct){ in: (#struct){ taxPayer: (#struct){ self: (#struct){ } } } _computed(:p): (#struct){ in: (#struct){ taxPayer: (#struct){ self: (#struct){ } } } } } } subject: (struct){ in: ~(#ReturnData) _computed(:p): (#struct){ in: ~(#ReturnData) } } #computeF1040: (#struct){ in: ~(#ReturnData) } #ReturnData: (#struct){ taxPayer?: ~(#TaxPayer) } #TaxPayer: (#struct){ self?: (_){ _ } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,22 +4,16 @@ } } let sam#1 = (struct){ - taxPayer: (struct){ - self: (struct){ - } - } + taxPayer: ~(_taxPayer(:p)) } assert: (struct){ invoke: (struct){ - taxPayer: (struct){ - self: (struct){ - } - } + taxPayer: ~(_taxPayer(:p)) } res: (struct){ in: (#struct){ taxPayer: (#struct){ - self: (struct){ + self: (#struct){ } } } @@ -26,7 +20,7 @@ _computed(:p): (#struct){ in: (#struct){ taxPayer: (#struct){ - self: (struct){ + self: (#struct){ } } } @@ -34,30 +28,16 @@ } } subject: (struct){ - in: (#struct){ - taxPayer?: (#struct){ - self?: (_){ _ } - } - } + in: ~(#ReturnData) _computed(:p): (#struct){ - in: (#struct){ - taxPayer?: (#struct){ - self?: (_){ _ } - } - } + in: ~(#ReturnData) } } #computeF1040: (#struct){ - in: (#struct){ - taxPayer?: (#struct){ - self?: (_){ _ } - } - } + in: ~(#ReturnData) } #ReturnData: (#struct){ - taxPayer?: (#struct){ - self?: (_){ _ } - } + taxPayer?: ~(#TaxPayer) } #TaxPayer: (#struct){ self?: (_){ _ } -- out/eval -- (struct){ _taxPayer(:p): (struct){ self: (struct){ } } let sam#1 = (struct){ taxPayer: (struct){ self: (struct){ } } } assert: (struct){ invoke: (struct){ taxPayer: (struct){ self: (struct){ } } } res: (struct){ in: (#struct){ taxPayer: (#struct){ self: (struct){ } } } _computed(:p): (#struct){ in: (#struct){ taxPayer: (#struct){ self: (struct){ } } } } } } subject: (struct){ in: (#struct){ taxPayer?: (#struct){ self?: (_){ _ } } } _computed(:p): (#struct){ in: (#struct){ taxPayer?: (#struct){ self?: (_){ _ } } } } } #computeF1040: (#struct){ in: (#struct){ taxPayer?: (#struct){ self?: (_){ _ } } } } #ReturnData: (#struct){ taxPayer?: (#struct){ self?: (_){ _ } } } #TaxPayer: (#struct){ self?: (_){ _ } } } -- out/compile -- --- in.cue { _taxPayer: { self: {} } let sam#1 = { taxPayer: 〈1;_taxPayer〉 } assert: { invoke: 〈1;let sam#1〉 invoke: _ res: (〈1;subject〉 & { in: 〈1;invoke〉 }) } subject: { in: 〈1;#ReturnData〉 _computed: (〈1;#computeF1040〉 & { in: 〈1;in〉 }) } #computeF1040: { in: 〈1;#ReturnData〉 } #ReturnData: { taxPayer?: 〈1;#TaxPayer〉 } #TaxPayer: { self?: _ } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue3571.txtar000066400000000000000000000142571474664451600227310ustar00rootroot00000000000000-- in.cue -- // These tests should NOT have structural cycles. simplified: { #T in: _ x: #T x: x: #T #T: { in: x x: _ } } issue3571: { a: #T a: in: f: true a: #in: { g: #T g: #in: f: #T g: #in: f: #in: x: true f?: _ } #T: { in: #in #in: _ } } -- out/eval/stats -- Leaks: 0 Freed: 54 Reused: 42 Allocs: 12 Retain: 19 Unifications: 54 Conjuncts: 125 Disjuncts: 73 -- out/evalalpha -- (struct){ simplified: (#struct){ in: (#struct){ x: (#struct){ in: (_){ _ } x: (_){ _ } } in: ~(simplified.in.x) } x: (#struct){ x: (#struct){ in: (_){ _ } x: (_){ _ } } in: ~(simplified.x.x) } #T: (#struct){ in: (_){ _ } x: (_){ _ } } } issue3571: (struct){ a: (#struct){ in: (#struct){ f: (bool){ true } g: (#struct){ #in: (#struct){ f: (#struct){ #in: (#struct){ x: (bool){ true } } in: ~(issue3571.a.in.g.#in.f.#in) } } in: ~(issue3571.a.in.g.#in) } } #in: (#struct){ g: (#struct){ #in: (#struct){ f: (#struct){ #in: (#struct){ x: (bool){ true } } in: ~(issue3571.a.#in.g.#in.f.#in) } } in: ~(issue3571.a.#in.g.#in) } f?: (_){ _ } } } #T: (#struct){ in: (_){ _ } #in: (_){ _ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,24 +1,18 @@ (struct){ simplified: (#struct){ in: (#struct){ - in: (#struct){ - in: (_){ _ } - x: (_){ _ } - } - x: (#struct){ - in: (_){ _ } - x: (_){ _ } - } + x: (#struct){ + in: (_){ _ } + x: (_){ _ } + } + in: ~(simplified.in.x) } x: (#struct){ - in: (#struct){ - in: (_){ _ } - x: (_){ _ } - } - x: (#struct){ - in: (_){ _ } - x: (_){ _ } - } + x: (#struct){ + in: (_){ _ } + x: (_){ _ } + } + in: ~(simplified.x.x) } #T: (#struct){ in: (_){ _ } @@ -28,52 +22,30 @@ issue3571: (struct){ a: (#struct){ in: (#struct){ - g: (#struct){ - in: (#struct){ - f: (#struct){ - in: (#struct){ - x: (bool){ true } - } - #in: (#struct){ - x: (bool){ true } - } - } - } - #in: (#struct){ - f: (#struct){ - in: (#struct){ - x: (bool){ true } - } - #in: (#struct){ - x: (bool){ true } - } - } - } - } f: (bool){ true } + g: (#struct){ + #in: (#struct){ + f: (#struct){ + #in: (#struct){ + x: (bool){ true } + } + in: ~(issue3571.a.in.g.#in.f.#in) + } + } + in: ~(issue3571.a.in.g.#in) + } } #in: (#struct){ g: (#struct){ - in: (#struct){ - f: (#struct){ - in: (#struct){ - x: (bool){ true } - } - #in: (#struct){ - x: (bool){ true } - } - } - } - #in: (#struct){ - f: (#struct){ - in: (#struct){ - x: (bool){ true } - } - #in: (#struct){ - x: (bool){ true } - } - } - } + #in: (#struct){ + f: (#struct){ + #in: (#struct){ + x: (bool){ true } + } + in: ~(issue3571.a.#in.g.#in.f.#in) + } + } + in: ~(issue3571.a.#in.g.#in) } f?: (_){ _ } } -- out/eval -- (struct){ simplified: (#struct){ in: (#struct){ in: (#struct){ in: (_){ _ } x: (_){ _ } } x: (#struct){ in: (_){ _ } x: (_){ _ } } } x: (#struct){ in: (#struct){ in: (_){ _ } x: (_){ _ } } x: (#struct){ in: (_){ _ } x: (_){ _ } } } #T: (#struct){ in: (_){ _ } x: (_){ _ } } } issue3571: (struct){ a: (#struct){ in: (#struct){ g: (#struct){ in: (#struct){ f: (#struct){ in: (#struct){ x: (bool){ true } } #in: (#struct){ x: (bool){ true } } } } #in: (#struct){ f: (#struct){ in: (#struct){ x: (bool){ true } } #in: (#struct){ x: (bool){ true } } } } } f: (bool){ true } } #in: (#struct){ g: (#struct){ in: (#struct){ f: (#struct){ in: (#struct){ x: (bool){ true } } #in: (#struct){ x: (bool){ true } } } } #in: (#struct){ f: (#struct){ in: (#struct){ x: (bool){ true } } #in: (#struct){ x: (bool){ true } } } } } f?: (_){ _ } } } #T: (#struct){ in: (_){ _ } #in: (_){ _ } } } } -- out/compile -- --- in.cue { simplified: { 〈0;#T〉 in: _ x: 〈0;#T〉 x: { x: 〈1;#T〉 } #T: { in: 〈0;x〉 x: _ } } issue3571: { a: 〈0;#T〉 a: { in: { f: true } } a: { #in: { g: 〈2;#T〉 g: { #in: { f: 〈4;#T〉 } } g: { #in: { f: { #in: { x: true } } } } f?: _ } } #T: { in: 〈0;#in〉 #in: _ } } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue429.txtar000066400000000000000000000270201474664451600226400ustar00rootroot00000000000000TODO: a bound value resolving to a disjunction should probably be an error. In this case #Size.amx should resolve. -- in.cue -- // Range disjunction without cycle (checks only one-way). #Size: { res: uint | *0 min: >res | *(1 + res) max: >min | *min } s0: #Size & {res: 1} // This discards the default for max. This is correct, but unfortunate. // TODO: is there a tweak to the default mechanism possible that would fix that? // Tread very carefully, though! Perhaps we could have a builtin that // discards any default, so that we can at least manually override this // behavior. s1: #Size & {min: 5} s2: #Size & {max: 5} s3: #Size & { min: 5 max: 10 } es3: #Size & { min: 10 max: 5 } // Disjunctions with cycles // TODO: improve error message here. Logic is correct, though. #nonEmptyRange: { min: *1 | int min: min } r1: #nonEmptyRange & { min: 3 } r2: #nonEmptyRange & { max: 5 } r3: #nonEmptyRange & { min: 3 max: 6 } er3: #nonEmptyRange & { min: 5 max: 5 } -- out/eval/stats -- Leaks: 0 Freed: 98 Reused: 91 Allocs: 7 Retain: 12 Unifications: 40 Conjuncts: 150 Disjuncts: 101 -- out/evalalpha -- Errors: er3.min: 2 errors in empty disjunction: er3.min: conflicting values 1 and 5: ./in.cue:28:8 ./in.cue:44:7 es3.max: 2 errors in empty disjunction: es3.max: 4 errors in empty disjunction: es3.max: conflicting values 1 and 5: ./in.cue:4:16 ./in.cue:22:7 es3.max: conflicting values 10 and 5: ./in.cue:21:7 ./in.cue:22:7 es3.max: invalid value 5 (out of bound >10): ./in.cue:5:7 ./in.cue:22:7 er3.min: invalid value 5 (out of bound <5): ./in.cue:29:7 ./in.cue:44:7 Result: (_|_){ // [eval] #Size: (#struct){ res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (number){ |(*(int){ 1 }, (number){ >0 }) } max: (number){ |(*(int){ 1 }, (number){ >0 }, (number){ >1 }) } } s0: (#struct){ res: (int){ 1 } min: (number){ |(*(int){ 2 }, (number){ >1 }) } max: (number){ |(*(int){ 2 }, (number){ >1 }, (number){ >2 }) } } s1: (#struct){ min: (int){ 5 } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } max: (number){ |((number){ >5 }, (int){ 5 }) } } s2: (#struct){ max: (int){ 5 } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (number){ |(*(int){ 1 }, (number){ >0 }) } } s3: (#struct){ min: (int){ 5 } max: (int){ 10 } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } } es3: (_|_){ // [eval] min: (int){ 10 } max: (_|_){ // [eval] es3.max: 2 errors in empty disjunction: // es3.max: 4 errors in empty disjunction: // es3.max: conflicting values 1 and 5: // ./in.cue:4:16 // ./in.cue:22:7 // es3.max: conflicting values 10 and 5: // ./in.cue:21:7 // ./in.cue:22:7 // es3.max: invalid value 5 (out of bound >10): // ./in.cue:5:7 // ./in.cue:22:7 } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } } #nonEmptyRange: (#struct){ min: (_|_){ // [cycle] cycle error } max: (_|_){ // [cycle] cycle error } } r1: (#struct){ min: (int){ 3 } max: (number){ >3 } } r2: (#struct){ max: (int){ 5 } min: (int){ |(*(int){ 1 }, (int){ &(<5, int) }) } } r3: (#struct){ min: (int){ 3 } max: (int){ 6 } } er3: (_|_){ // [eval] min: (_|_){ // [eval] er3.min: 2 errors in empty disjunction: // er3.min: conflicting values 1 and 5: // ./in.cue:28:8 // ./in.cue:44:7 // er3.min: invalid value 5 (out of bound <5): // ./in.cue:29:7 // ./in.cue:44:7 } max: (_|_){ // [eval] er3.min: 2 errors in empty disjunction: // er3.min: conflicting values 1 and 5: // ./in.cue:28:8 // ./in.cue:44:7 // er3.min: invalid value 5 (out of bound <5): // ./in.cue:29:7 // ./in.cue:44:7 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,17 +2,13 @@ er3.min: 2 errors in empty disjunction: er3.min: conflicting values 1 and 5: ./in.cue:28:8 - ./in.cue:43:6 - ./in.cue:44:7 -es3.max: 3 errors in empty disjunction: + ./in.cue:44:7 +es3.max: 2 errors in empty disjunction: +es3.max: 4 errors in empty disjunction: es3.max: conflicting values 1 and 5: ./in.cue:4:16 - ./in.cue:5:15 - ./in.cue:20:6 ./in.cue:22:7 es3.max: conflicting values 10 and 5: - ./in.cue:5:15 - ./in.cue:20:6 ./in.cue:21:7 ./in.cue:22:7 es3.max: invalid value 5 (out of bound >10): @@ -36,34 +32,30 @@ max: (number){ |(*(int){ 2 }, (number){ >1 }, (number){ >2 }) } } s1: (#struct){ - res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } - min: (int){ 5 } - max: (number){ |(*(int){ 5 }, (number){ >5 }) } + min: (int){ 5 } + res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } + max: (number){ |((number){ >5 }, (int){ 5 }) } } s2: (#struct){ - res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } - min: (number){ |(*(int){ 1 }, (number){ >0 }) } - max: (int){ 5 } + max: (int){ 5 } + res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } + min: (number){ |(*(int){ 1 }, (number){ >0 }) } } s3: (#struct){ - res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 5 } max: (int){ 10 } + res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } } es3: (_|_){ // [eval] - res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 10 } max: (_|_){ - // [eval] es3.max: 3 errors in empty disjunction: + // [eval] es3.max: 2 errors in empty disjunction: + // es3.max: 4 errors in empty disjunction: // es3.max: conflicting values 1 and 5: // ./in.cue:4:16 - // ./in.cue:5:15 - // ./in.cue:20:6 // ./in.cue:22:7 // es3.max: conflicting values 10 and 5: - // ./in.cue:5:15 - // ./in.cue:20:6 // ./in.cue:21:7 // ./in.cue:22:7 // es3.max: invalid value 5 (out of bound >10): @@ -70,12 +62,15 @@ // ./in.cue:5:7 // ./in.cue:22:7 } + res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } } #nonEmptyRange: (#struct){ min: (_|_){ // [cycle] cycle error } - max: (number){ >1 } + max: (_|_){ + // [cycle] cycle error + } } r1: (#struct){ min: (int){ 3 } @@ -82,8 +77,8 @@ max: (number){ >3 } } r2: (#struct){ + max: (int){ 5 } min: (int){ |(*(int){ 1 }, (int){ &(<5, int) }) } - max: (int){ 5 } } r3: (#struct){ min: (int){ 3 } @@ -95,17 +90,15 @@ // [eval] er3.min: 2 errors in empty disjunction: // er3.min: conflicting values 1 and 5: // ./in.cue:28:8 - // ./in.cue:43:6 - // ./in.cue:44:7 - // er3.min: invalid value 5 (out of bound <5): - // ./in.cue:29:7 - // ./in.cue:44:7 - } - max: (_|_){ - // [eval] er3.min: 2 errors in empty disjunction: - // er3.min: conflicting values 1 and 5: - // ./in.cue:28:8 - // ./in.cue:43:6 + // ./in.cue:44:7 + // er3.min: invalid value 5 (out of bound <5): + // ./in.cue:29:7 + // ./in.cue:44:7 + } + max: (_|_){ + // [eval] er3.min: 2 errors in empty disjunction: + // er3.min: conflicting values 1 and 5: + // ./in.cue:28:8 // ./in.cue:44:7 // er3.min: invalid value 5 (out of bound <5): // ./in.cue:29:7 -- diff/todo/p2 -- #nonEmptyRange: missing disjunction error, or at least missing validation. At least this seems more correct than the old evaluator. It is an incomplete error at best. -- diff/explanation -- s1.max: the changes in default behavior as are shown here are according to spec, as is described in disjunctions/specdeviation.txtar. These changes may pose too much of a problem for the transition to the new evaluator, though. TODO: consider reintroducing bugs. -- diff/todo/p3 -- Reordering. Missing empty disjunction message. Missing error positions. -- out/eval -- Errors: er3.min: 2 errors in empty disjunction: er3.min: conflicting values 1 and 5: ./in.cue:28:8 ./in.cue:43:6 ./in.cue:44:7 es3.max: 3 errors in empty disjunction: es3.max: conflicting values 1 and 5: ./in.cue:4:16 ./in.cue:5:15 ./in.cue:20:6 ./in.cue:22:7 es3.max: conflicting values 10 and 5: ./in.cue:5:15 ./in.cue:20:6 ./in.cue:21:7 ./in.cue:22:7 es3.max: invalid value 5 (out of bound >10): ./in.cue:5:7 ./in.cue:22:7 er3.min: invalid value 5 (out of bound <5): ./in.cue:29:7 ./in.cue:44:7 Result: (_|_){ // [eval] #Size: (#struct){ res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (number){ |(*(int){ 1 }, (number){ >0 }) } max: (number){ |(*(int){ 1 }, (number){ >0 }, (number){ >1 }) } } s0: (#struct){ res: (int){ 1 } min: (number){ |(*(int){ 2 }, (number){ >1 }) } max: (number){ |(*(int){ 2 }, (number){ >1 }, (number){ >2 }) } } s1: (#struct){ res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 5 } max: (number){ |(*(int){ 5 }, (number){ >5 }) } } s2: (#struct){ res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (number){ |(*(int){ 1 }, (number){ >0 }) } max: (int){ 5 } } s3: (#struct){ res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 5 } max: (int){ 10 } } es3: (_|_){ // [eval] res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 10 } max: (_|_){ // [eval] es3.max: 3 errors in empty disjunction: // es3.max: conflicting values 1 and 5: // ./in.cue:4:16 // ./in.cue:5:15 // ./in.cue:20:6 // ./in.cue:22:7 // es3.max: conflicting values 10 and 5: // ./in.cue:5:15 // ./in.cue:20:6 // ./in.cue:21:7 // ./in.cue:22:7 // es3.max: invalid value 5 (out of bound >10): // ./in.cue:5:7 // ./in.cue:22:7 } } #nonEmptyRange: (#struct){ min: (_|_){ // [cycle] cycle error } max: (number){ >1 } } r1: (#struct){ min: (int){ 3 } max: (number){ >3 } } r2: (#struct){ min: (int){ |(*(int){ 1 }, (int){ &(<5, int) }) } max: (int){ 5 } } r3: (#struct){ min: (int){ 3 } max: (int){ 6 } } er3: (_|_){ // [eval] min: (_|_){ // [eval] er3.min: 2 errors in empty disjunction: // er3.min: conflicting values 1 and 5: // ./in.cue:28:8 // ./in.cue:43:6 // ./in.cue:44:7 // er3.min: invalid value 5 (out of bound <5): // ./in.cue:29:7 // ./in.cue:44:7 } max: (_|_){ // [eval] er3.min: 2 errors in empty disjunction: // er3.min: conflicting values 1 and 5: // ./in.cue:28:8 // ./in.cue:43:6 // ./in.cue:44:7 // er3.min: invalid value 5 (out of bound <5): // ./in.cue:29:7 // ./in.cue:44:7 } } } -- out/compile -- --- in.cue { #Size: { res: (&(int, >=0)|*0) min: (>〈0;res〉|*(1 + 〈0;res〉)) max: (>〈0;min〉|*〈0;min〉) } s0: (〈0;#Size〉 & { res: 1 }) s1: (〈0;#Size〉 & { min: 5 }) s2: (〈0;#Size〉 & { max: 5 }) s3: (〈0;#Size〉 & { min: 5 max: 10 }) es3: (〈0;#Size〉 & { min: 10 max: 5 }) #nonEmptyRange: { min: (*1|int) min: <〈0;max〉 max: >〈0;min〉 } r1: (〈0;#nonEmptyRange〉 & { min: 3 }) r2: (〈0;#nonEmptyRange〉 & { max: 5 }) r3: (〈0;#nonEmptyRange〉 & { min: 3 max: 6 }) er3: (〈0;#nonEmptyRange〉 & { min: 5 max: 5 }) } cue-lang-cue-db9cc73/cue/testdata/cycle/issue494.txtar000066400000000000000000000106561474664451600226510ustar00rootroot00000000000000-- in.cue -- _Q: [{pos: 0}, {pos: 1}] a: [rn=string]: _Q[0:len(a[rn])] a: ben: [{}] b: [rn=string]: _Q[0:1] b: ben: [{}] c: [rn=string]: [...{l: len(a[rn])}] c: ben: [{}] #d: [rn=string]: [...{pos: uint}] & _Q[0:len(#d[rn])] #d: ben: [{}] d: #d e: [rn=string]: _Q[0 : len(a[rn])+1] e: ben: [{}, ...] f: [rn=string]: _Q[0 : len(a[rn])+1] f: ben: [{}] g: [rn=string]: _Q[0:len(a[rn])] g: ben: [{}, {}] -- out/eval/stats -- Leaks: 0 Freed: 43 Reused: 38 Allocs: 5 Retain: 0 Unifications: 43 Conjuncts: 83 Disjuncts: 45 -- out/evalalpha -- Errors: f.ben: incompatible list lengths (1 and 2) g.ben: incompatible list lengths (1 and 2) Result: (_|_){ // [eval] _Q: (#list){ 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } a: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } b: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } c: (struct){ ben: (#list){ 0: (struct){ l: (int){ 1 } } } } #d: (#struct){ ben: (#list){ 0: (#struct){ pos: (int){ 0 } } } } d: ~(#d) e: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } } f: (_|_){ // [eval] ben: (_|_){ // [eval] f.ben: incompatible list lengths (1 and 2) 0: (struct){ } } } g: (_|_){ // [eval] ben: (_|_){ // [eval] g.ben: incompatible list lengths (1 and 2) 0: (struct){ } 1: (struct){ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -41,13 +41,7 @@ } } } - d: (#struct){ - ben: (#list){ - 0: (#struct){ - pos: (int){ 0 } - } - } - } + d: ~(#d) e: (struct){ ben: (#list){ 0: (struct){ @@ -63,10 +57,6 @@ ben: (_|_){ // [eval] f.ben: incompatible list lengths (1 and 2) 0: (struct){ - pos: (int){ 0 } - } - 1: (struct){ - pos: (int){ 1 } } } } @@ -75,7 +65,6 @@ ben: (_|_){ // [eval] g.ben: incompatible list lengths (1 and 2) 0: (struct){ - pos: (int){ 0 } } 1: (struct){ } -- diff/todo/p2 -- error path moved -- out/eval -- Errors: f.ben: incompatible list lengths (1 and 2) g.ben: incompatible list lengths (1 and 2) Result: (_|_){ // [eval] _Q: (#list){ 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } a: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } b: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } c: (struct){ ben: (#list){ 0: (struct){ l: (int){ 1 } } } } #d: (#struct){ ben: (#list){ 0: (#struct){ pos: (int){ 0 } } } } d: (#struct){ ben: (#list){ 0: (#struct){ pos: (int){ 0 } } } } e: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } } f: (_|_){ // [eval] ben: (_|_){ // [eval] f.ben: incompatible list lengths (1 and 2) 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } } g: (_|_){ // [eval] ben: (_|_){ // [eval] g.ben: incompatible list lengths (1 and 2) 0: (struct){ pos: (int){ 0 } } 1: (struct){ } } } } -- out/compile -- --- in.cue { _Q: [ { pos: 0 }, { pos: 1 }, ] a: { [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] } a: { ben: [ {}, ] } b: { [string]: 〈1;_Q〉[0:1] } b: { ben: [ {}, ] } c: { [string]: [ ...{ l: len(〈3;a〉[〈2;-〉]) }, ] } c: { ben: [ {}, ] } #d: { [string]: ([ ...{ pos: &(int, >=0) }, ] & 〈1;_Q〉[0:len(〈1;#d〉[〈0;-〉])]) } #d: { ben: [ {}, ] } d: 〈0;#d〉 e: { [string]: 〈1;_Q〉[0:(len(〈1;a〉[〈0;-〉]) + 1)] } e: { ben: [ {}, ..., ] } f: { [string]: 〈1;_Q〉[0:(len(〈1;a〉[〈0;-〉]) + 1)] } f: { ben: [ {}, ] } g: { [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] } g: { ben: [ {}, {}, ] } } cue-lang-cue-db9cc73/cue/testdata/cycle/issue502.txtar000066400000000000000000000113131474664451600226260ustar00rootroot00000000000000-- in.cue -- #T: { config: _ body: _ mas: [string]: { cfg: _ _link: #T link: _link & {config: cfg} } } #a: #T & { config: a: int body: config.a mas: one: { cfg: b: config.a _link: { config: b: int body: config.b mas: two: { cfg: c: config.b _link: { config: c: int body: config.c } } } } } a: #a & {config: a: 34} -- out/eval/stats -- Leaks: 0 Freed: 93 Reused: 83 Allocs: 10 Retain: 0 Unifications: 93 Conjuncts: 264 Disjuncts: 93 -- out/eval -- (struct){ #T: (#struct){ config: (_){ _ } body: (_){ _ } mas: (#struct){ } } #a: (#struct){ config: (#struct){ a: (int){ int } } body: (int){ int } mas: (#struct){ one: (#struct){ cfg: (#struct){ b: (int){ int } } _link: (#struct){ config: (#struct){ b: (int){ int } } body: (int){ int } mas: (#struct){ two: (#struct){ cfg: (#struct){ c: (int){ int } } _link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } } } } link: (#struct){ config: (#struct){ b: (int){ int } } body: (int){ int } mas: (#struct){ two: (#struct){ cfg: (#struct){ c: (int){ int } } _link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } } } } } } } a: (#struct){ config: (#struct){ a: (int){ 34 } } body: (int){ 34 } mas: (#struct){ one: (#struct){ cfg: (#struct){ b: (int){ 34 } } _link: (#struct){ config: (#struct){ b: (int){ int } } body: (int){ int } mas: (#struct){ two: (#struct){ cfg: (#struct){ c: (int){ int } } _link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } } } } link: (#struct){ config: (#struct){ b: (int){ 34 } } body: (int){ 34 } mas: (#struct){ two: (#struct){ cfg: (#struct){ c: (int){ 34 } } _link: (#struct){ config: (#struct){ c: (int){ int } } body: (int){ int } mas: (#struct){ } } link: (#struct){ config: (#struct){ c: (int){ 34 } } body: (int){ 34 } mas: (#struct){ } } } } } } } } } -- out/compile -- --- in.cue { #T: { config: _ body: _ mas: { [string]: { cfg: _ _link: 〈3;#T〉 link: (〈0;_link〉 & { config: 〈1;cfg〉 }) } } } #a: (〈0;#T〉 & { config: { a: int } body: 〈0;config〉.a mas: { one: { cfg: { b: 〈3;config〉.a } _link: { config: { b: int } body: 〈0;config〉.b mas: { two: { cfg: { c: 〈3;config〉.b } _link: { config: { c: int } body: 〈0;config〉.c } } } } } } }) a: (〈0;#a〉 & { config: { a: 34 } }) } cue-lang-cue-db9cc73/cue/testdata/cycle/issue990.txtar000066400000000000000000000577471474664451600226660ustar00rootroot00000000000000-- in.cue -- // A simple discriminated element #AC: { k: "simple" d: #C } // A recursive discriminated element #AS: { k: "complex" d: #S } #R: { a: #AC | #AS } // The structure of the recursive element #S: { n: string r: [string]: #R } // The structure of the simple element #C: { n: string } #sub: { $p=#p: #AS dict: [string]: _ for rn, rd in $p.d.r if rd.a.k == "complex" { let subs = #sub & {#p: rd.a} for sn, sd in subs.dict { dict: "\(rn)_\(sn)": sd } } for rn, rd in $p.d.r if rd.a.k == "simple" { dict: "\(rn)": rd } } // Data _test: { c1: #AC c1: d: { n: "c1" } s3: #AS s3: d: { n: "s3" r: r1: a:c1 } s2: #AS s2: d: { n: "s2" r: { r1: a: c1 r2: a: s3 } } s1: #AS s1: d: { n: "s1" r: { r1: a: c1 r2: a: s2 } } } // Test out: #sub & {#p: _test.s1} -- diff/todo/p3 -- Reordering -- out/evalalpha/stats -- Leaks: 1184 Freed: 81 Reused: 81 Allocs: 1184 Retain: 0 Unifications: 243 Conjuncts: 4276 Disjuncts: 204 -- out/evalalpha -- (struct){ #AC: (#struct){ k: (string){ "simple" } d: ~(#C) } #AS: (#struct){ k: (string){ "complex" } d: ~(#S) } #R: (#struct){ a: (#struct){ |((#struct){ k: (string){ "simple" } d: ~(#C) }, (#struct){ k: (string){ "complex" } d: ~(#S) }) } } #S: (#struct){ n: (string){ string } r: (#struct){ } } #C: (#struct){ n: (string){ string } } #sub: (#struct){ #p: ~(#AS) dict: (#struct){ } let subs#1multi = (〈3;#sub〉 & { #p: 〈2;rd〉.a }) } _test: (struct){ c1: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } s3: (#struct){ d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } } } k: (string){ "complex" } } s2: (#struct){ d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } } } k: (string){ "complex" } } } } } k: (string){ "complex" } } s1: (#struct){ d: (#struct){ n: (string){ "s1" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } } } k: (string){ "complex" } } } } } k: (string){ "complex" } } } } } k: (string){ "complex" } } } out: (#struct){ #p: (#struct){ d: (#struct){ n: (string){ "s1" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } } } k: (string){ "complex" } } } } } k: (string){ "complex" } } } } } k: (string){ "complex" } } dict: (#struct){ r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2_r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } r2_r2_r1: (#struct){ a: (#struct){ d: (#struct){ n: (string){ "c1" } } k: (string){ "simple" } } } } let subs#1multi = (〈3;#sub〉 & { #p: 〈2;rd〉.a }) } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 6 -Freed: 3232 -Reused: 3213 -Allocs: 25 -Retain: 26 +Leaks: 1184 +Freed: 81 +Reused: 81 +Allocs: 1184 +Retain: 0 -Unifications: 2588 -Conjuncts: 12056 -Disjuncts: 3258 +Unifications: 243 +Conjuncts: 4276 +Disjuncts: 204 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,31 +1,19 @@ (struct){ #AC: (#struct){ k: (string){ "simple" } - d: (#struct){ - n: (string){ string } - } + d: ~(#C) } #AS: (#struct){ k: (string){ "complex" } - d: (#struct){ - n: (string){ string } - r: (#struct){ - } - } + d: ~(#S) } #R: (#struct){ a: (#struct){ |((#struct){ k: (string){ "simple" } - d: (#struct){ - n: (string){ string } - } + d: ~(#C) }, (#struct){ k: (string){ "complex" } - d: (#struct){ - n: (string){ string } - r: (#struct){ - } - } + d: ~(#S) }) } } #S: (#struct){ @@ -37,14 +25,7 @@ n: (string){ string } } #sub: (#struct){ - #p: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ string } - r: (#struct){ - } - } - } + #p: ~(#AS) dict: (#struct){ } let subs#1multi = (〈3;#sub〉 & { @@ -53,190 +34,190 @@ } _test: (struct){ c1: (#struct){ - k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } + k: (string){ "simple" } } s3: (#struct){ - k: (string){ "complex" } d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - } - } + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + } + } + k: (string){ "complex" } } s2: (#struct){ - k: (string){ "complex" } d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - r2: (#struct){ - a: (#struct){ - k: (string){ "complex" } + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + r2: (#struct){ + a: (#struct){ d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - } - } - } - } - } - } + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + } + } + k: (string){ "complex" } + } + } + } + } + k: (string){ "complex" } } s1: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ "s1" } - r: (#struct){ - r1: (#struct){ - a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - r2: (#struct){ - a: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ "s2" } - r: (#struct){ - r1: (#struct){ - a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - r2: (#struct){ - a: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ "s3" } - r: (#struct){ - r1: (#struct){ - a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - } - } - } - } - } - } - } - } - } - } + d: (#struct){ + n: (string){ "s1" } + r: (#struct){ + r1: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + r2: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "s2" } + r: (#struct){ + r1: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + r2: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "s3" } + r: (#struct){ + r1: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + } + } + k: (string){ "complex" } + } + } + } + } + k: (string){ "complex" } + } + } + } + } + k: (string){ "complex" } } } out: (#struct){ #p: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ "s1" } - r: (#struct){ - r1: (#struct){ - a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - r2: (#struct){ - a: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ "s2" } - r: (#struct){ - r1: (#struct){ - a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - r2: (#struct){ - a: (#struct){ - k: (string){ "complex" } - d: (#struct){ - n: (string){ "s3" } - r: (#struct){ - r1: (#struct){ - a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } - } - } - } - } - } - } - } - } - } - } - } - } + d: (#struct){ + n: (string){ "s1" } + r: (#struct){ + r1: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + r2: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "s2" } + r: (#struct){ + r1: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + r2: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "s3" } + r: (#struct){ + r1: (#struct){ + a: (#struct){ + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } + } + } + } + } + k: (string){ "complex" } + } + } + } + } + k: (string){ "complex" } + } + } + } + } + k: (string){ "complex" } } dict: (#struct){ r1: (#struct){ a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } } } r2_r1: (#struct){ a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } } } r2_r2_r1: (#struct){ a: (#struct){ - k: (string){ "simple" } - d: (#struct){ - n: (string){ "c1" } - } + d: (#struct){ + n: (string){ "c1" } + } + k: (string){ "simple" } } } } -- out/eval/stats -- Leaks: 6 Freed: 3232 Reused: 3213 Allocs: 25 Retain: 26 Unifications: 2588 Conjuncts: 12056 Disjuncts: 3258 -- out/eval -- (struct){ #AC: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ string } } } #AS: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ string } r: (#struct){ } } } #R: (#struct){ a: (#struct){ |((#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ string } } }, (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ string } r: (#struct){ } } }) } } #S: (#struct){ n: (string){ string } r: (#struct){ } } #C: (#struct){ n: (string){ string } } #sub: (#struct){ #p: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ string } r: (#struct){ } } } dict: (#struct){ } let subs#1multi = (〈3;#sub〉 & { #p: 〈2;rd〉.a }) } _test: (struct){ c1: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } s3: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } } } } s2: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2: (#struct){ a: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } } } } } } } } s1: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s1" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2: (#struct){ a: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2: (#struct){ a: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } } } } } } } } } } } } } out: (#struct){ #p: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s1" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2: (#struct){ a: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s2" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2: (#struct){ a: (#struct){ k: (string){ "complex" } d: (#struct){ n: (string){ "s3" } r: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } } } } } } } } } } } } dict: (#struct){ r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2_r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } r2_r2_r1: (#struct){ a: (#struct){ k: (string){ "simple" } d: (#struct){ n: (string){ "c1" } } } } } let subs#1multi = (〈3;#sub〉 & { #p: 〈2;rd〉.a }) } } -- out/compile -- --- in.cue { #AC: { k: "simple" d: 〈1;#C〉 } #AS: { k: "complex" d: 〈1;#S〉 } #R: { a: (〈1;#AC〉|〈1;#AS〉) } #S: { n: string r: { [string]: 〈2;#R〉 } } #C: { n: string } #sub: { #p: 〈1;#AS〉 dict: { [string]: _ } for rn, rd in 〈0;#p〉.d.r if (〈0;rd〉.a.k == "complex") { let subs#1multi = (〈3;#sub〉 & { #p: 〈2;rd〉.a }) for sn, sd in 〈0;let subs#1〉.dict { dict: { "\(〈4;rn〉)_\(〈2;sn〉)": 〈2;sd〉 } } } for rn, rd in 〈0;#p〉.d.r if (〈0;rd〉.a.k == "simple") { dict: { "\(〈2;rn〉)": 〈2;rd〉 } } } _test: { c1: 〈1;#AC〉 c1: { d: { n: "c1" } } s3: 〈1;#AS〉 s3: { d: { n: "s3" r: { r1: { a: 〈4;c1〉 } } } } s2: 〈1;#AS〉 s2: { d: { n: "s2" r: { r1: { a: 〈4;c1〉 } r2: { a: 〈4;s3〉 } } } } s1: 〈1;#AS〉 s1: { d: { n: "s1" r: { r1: { a: 〈4;c1〉 } r2: { a: 〈4;s2〉 } } } } } out: (〈0;#sub〉 & { #p: 〈1;_test〉.s1 }) } cue-lang-cue-db9cc73/cue/testdata/cycle/patterns.txtar000066400000000000000000000034621474664451600231150ustar00rootroot00000000000000// Excluded from V2, which no longer passes. Lots of cycle-reference goodness. -- in.cue -- [!~"^[.]"]: c a: b b: [string]: int c: a: int [string]: c a: b b: [string]: int c: a: int -- issue3326.cue -- issue3326: { // This issue triggered a cyclic evaluation in pattern constraints. // // It seems like there is still an issue as the evaluation of `x` in // `and` may trigger a cyclic evaluation of `and`. However, `and` only // does a shallow evaluation, and inserting `x`'s conjuncts into itself // is identified as idempotent and thus further evaluation is skipped. _self: x: [...and(x)] _self x: [1] } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 2 Allocs: 5 Retain: 2 Unifications: 7 Conjuncts: 59 Disjuncts: 9 -- out/evalalpha -- (struct){ a: (struct){ a: (int){ int } } b: (struct){ a: (int){ int } } c: (struct){ a: (int){ int } } issue3326: (struct){ _self: (struct){ x: (list){ } } x: (#list){ 0: (int){ 1 } } a: (int){ int } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -8,4 +8,14 @@ c: (struct){ a: (int){ int } } + issue3326: (struct){ + _self: (struct){ + x: (list){ + } + } + x: (#list){ + 0: (int){ 1 } + } + a: (int){ int } + } } -- out/eval -- (struct){ a: (struct){ a: (int){ int } } b: (struct){ a: (int){ int } } c: (struct){ a: (int){ int } } } -- out/compile -- --- in.cue { [!~"^[.]"]: 〈0;c〉 a: 〈0;b〉 b: { [string]: int } c: { a: int } [string]: 〈0;c〉 a: 〈0;b〉 b: { [string]: int } c: { a: int } } --- issue3326.cue { issue3326: { _self: { x: [ ...and(〈1;x〉), ] } 〈0;_self〉 x: [ 1, ] } } cue-lang-cue-db9cc73/cue/testdata/cycle/self.txtar000066400000000000000000000624341474664451600222120ustar00rootroot00000000000000-- in.cue -- import "list" expr: error1: { a: 3 a: a + 1 } expr: error2: { a: a + 1 a: 3 } list: error1: { a: ["1", "2"] a: list.Concat([a, ["3"]]) } list: error2: { a: list.Concat([["3"], a]) a: ["1", "2"] } selfEmbed: ok1: { a: x Y: x x: {Y} } selfEmbed: ok2: { Y: x.b a: x x: b: {Y} } selfEmbed: ok3: { Y: x a: x x: {Y} } selfEmbed: ok4: { a: x x: {Y} Y: x } selfEmbed: ok5: { x: {Y} a: x Y: x } selfEmbed: ok6: { x: b: {Y} Y: x.b a: x } disjSelf: ok1: { #A: string | #A x: #A } disjSelf: ok2: { x: #A #A: string | #A } disjSelf: ok3: { #A: #A | string x: #A } disjSelf: ok4: { x: #A #A: #A | string } disjEmbed: ok1: { #A: string | {#A} x: #A } disjEmbed: ok2: { x: #A #A: string | {#A} } disjEmbed: ok3: { #A: {#A} | string x: #A } disjEmbed: ok4: { x: #A #A: {#A} | string } // x and #A should yield the same result. disjList: _ disjList: ok1: { #A: string | [#A] x: #A y: x y: [[[[string]]]] } disjList: ok2: { x: #A #A: string | [#A] } disjList: ok3: { #A: [#A] | string x: #A } disjList: ok4: { x: #A #A: [#A] | string } name: "foo" dynamicSelf: ok1: { X=(name): string | X x: X } dynamicSelf: ok2: { x: X X=(name): string | X } dynamicSelf: ok3: { X=(name): X | string x: X } dynamicSelf: ok4: { x: X X=(name): X | string } dynamicEmbed: ok1: { X=(name): string | {X} x: X } dynamicEmbed: ok2: { x: X X=(name): string | {X} } dynamicEmbed: ok3: { X=(name): {X} | string x: X } dynamicEmbed: ok4: { x: X X=(name): {X} | string } dynamicList: _ dynamicList: ok1: { X=(name): string | [X] x: X y: x y: [[[[string]]]] } dynamicList: ok2: { x: X X=(name): string | [X] } dynamicList: ok3: { X=(name): [X] | string x: X } dynamicList: ok4: { x: X X=(name): [X] | string } dynamicPatternSelf: ok1: { X=[string]: string | X } dynamicPatternSelf: ok2: { X=[string]: X | string } dynamicPatternEmbed: ok1: { X=[string]: string | {X} } dynamicPatternEmbed: ok2: { X=[string]: {X} | string } dynamicPatternList: ok1: { X=[string]: string | [X] } dynamicPatternList: ok2: { X=[string]: [X] | string } valueSelf: ok1: { y: X={string | X} x: y } valueSelf: ok2: { x: y y: X={string | X} } valueSelf: ok3: { y: X={X | string} x: y } valueSelf: ok4: { x: y y: X={X | string} } valueEmbed: ok1: { y: X={string | {X}} x: y } valueEmbed: ok2: { x: y y: X={string | {X}} } valueEmbed: ok3: { y: X={{X} | string} x: y } valueEmbed: ok4: { x: y y: X={{X} | string} } valueList: ok1: { y: X={string | [X]} x: y } valueList: ok2: { x: y y: X={string | [X]} } valueList: ok3: { y: X={[X] | string} x: y } valueList: ok4: { x: y y: X={[X] | string} } // Issue #1729 issue1729: t1: { #x: { #x | {} } x: #x & {} } issue1729: t2: { x: #x & {} #x: { #x | {} } } -- out/eval/stats -- Leaks: 0 Freed: 432 Reused: 423 Allocs: 9 Retain: 15 Unifications: 240 Conjuncts: 663 Disjuncts: 447 -- out/evalalpha -- Errors: expr.error1.a: conflicting values 4 and 3: ./in.cue:4:5 ./in.cue:5:5 expr.error2.a: conflicting values 4 and 3: ./in.cue:8:5 ./in.cue:9:5 0: structural cycle: ./in.cue:13:5 1: structural cycle: ./in.cue:17:5 Result: (_|_){ // [eval] expr: (_|_){ // [eval] error1: (_|_){ // [eval] a: (_|_){ // [eval] expr.error1.a: conflicting values 4 and 3: // ./in.cue:4:5 // ./in.cue:5:5 } } error2: (_|_){ // [eval] a: (_|_){ // [eval] expr.error2.a: conflicting values 4 and 3: // ./in.cue:8:5 // ./in.cue:9:5 } } } list: (_|_){ // [structural cycle] error1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: structural cycle: // ./in.cue:13:5 } } error2: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 1: structural cycle: // ./in.cue:17:5 } } } selfEmbed: (struct){ ok1: (struct){ a: (struct){ } Y: (struct){ } x: (struct){ } } ok2: (struct){ Y: (struct){ } a: ~(selfEmbed.ok2.x) x: (struct){ b: (struct){ } } } ok3: (struct){ Y: (struct){ } a: (struct){ } x: (struct){ } } ok4: (struct){ a: (struct){ } x: (struct){ } Y: (struct){ } } ok5: (struct){ x: (struct){ } a: (struct){ } Y: (struct){ } } ok6: (struct){ x: (struct){ b: (struct){ } } Y: (struct){ } a: ~(selfEmbed.ok6.x) } } disjSelf: (struct){ ok1: (struct){ #A: (_){ |((string){ string }, (_){ _ }) } x: (_){ |((string){ string }, (_){ _ }) } } ok2: (struct){ x: (_){ |((string){ string }, (_){ _ }) } #A: (_){ |((string){ string }, (_){ _ }) } } ok3: (struct){ #A: (_){ |((_){ _ }, (string){ string }) } x: (_){ |((_){ _ }, (string){ string }) } } ok4: (struct){ x: (_){ |((_){ _ }, (string){ string }) } #A: (_){ |((_){ _ }, (string){ string }) } } } disjEmbed: (struct){ ok1: (struct){ #A: ((string|struct)){ |((string){ string }, (#struct){ }) } x: ((string|struct)){ |((string){ string }, (#struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (#struct){ }) } #A: ((string|struct)){ |((string){ string }, (#struct){ }) } } ok3: (struct){ #A: ((string|struct)){ |((#struct){ }, (string){ string }) } x: ((string|struct)){ |((#struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((#struct){ }, (string){ string }) } #A: ((string|struct)){ |((#struct){ }, (string){ string }) } } } disjList: (struct){ ok1: (struct){ #A: (string){ string } x: (string){ string } y: (#list){ 0: (#list){ 0: (#list){ 0: (#list){ 0: (string){ string } } } } } } ok2: (struct){ x: (string){ string } #A: (string){ string } } ok3: (struct){ #A: (string){ string } x: (string){ string } } ok4: (struct){ x: (string){ string } #A: (string){ string } } } name: (string){ "foo" } dynamicSelf: (struct){ ok1: (struct){ x: (_){ |((string){ string }, (_){ _ }) } foo: (_){ |((string){ string }, (_){ _ }) } } ok2: (struct){ x: (_){ |((string){ string }, (_){ _ }) } foo: (_){ |((string){ string }, (_){ _ }) } } ok3: (struct){ x: (_){ |((_){ _ }, (string){ string }) } foo: (_){ |((_){ _ }, (string){ string }) } } ok4: (struct){ x: (_){ |((_){ _ }, (string){ string }) } foo: (_){ |((_){ _ }, (string){ string }) } } } dynamicEmbed: (struct){ ok1: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } foo: ((string|struct)){ |((string){ string }, (struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } foo: ((string|struct)){ |((string){ string }, (struct){ }) } } ok3: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } foo: ((string|struct)){ |((struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } foo: ((string|struct)){ |((struct){ }, (string){ string }) } } } dynamicList: (struct){ ok1: (struct){ x: (string){ string } y: (#list){ 0: (#list){ 0: (#list){ 0: (#list){ 0: (string){ string } } } } } foo: (string){ string } } ok2: (struct){ x: (string){ string } foo: (string){ string } } ok3: (struct){ x: (string){ string } foo: (string){ string } } ok4: (struct){ x: (string){ string } foo: (string){ string } } } dynamicPatternSelf: (struct){ ok1: (struct){ } ok2: (struct){ } } dynamicPatternEmbed: (struct){ ok1: (struct){ } ok2: (struct){ } } dynamicPatternList: (struct){ ok1: (struct){ } ok2: (struct){ } } valueSelf: (struct){ ok1: (struct){ y: ((string|struct)){ |((string){ string }, (struct){ }) } x: ((string|struct)){ |((string){ string }, (struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } y: ((string|struct)){ |((string){ string }, (struct){ }) } } ok3: (struct){ y: ((string|struct)){ |((struct){ }, (string){ string }) } x: ((string|struct)){ |((struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } y: ((string|struct)){ |((struct){ }, (string){ string }) } } } valueEmbed: (struct){ ok1: (struct){ y: ((string|struct)){ |((string){ string }, (struct){ }) } x: ((string|struct)){ |((string){ string }, (struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } y: ((string|struct)){ |((string){ string }, (struct){ }) } } ok3: (struct){ y: ((string|struct)){ |((struct){ }, (string){ string }) } x: ((string|struct)){ |((struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } y: ((string|struct)){ |((struct){ }, (string){ string }) } } } valueList: (struct){ ok1: (struct){ y: (string){ string } x: (string){ string } } ok2: (struct){ x: (string){ string } y: (string){ string } } ok3: (struct){ y: (string){ string } x: (string){ string } } ok4: (struct){ x: (string){ string } y: (string){ string } } } issue1729: (struct){ t1: (struct){ #x: (#struct){ } x: (#struct){ } } t2: (struct){ x: (#struct){ } #x: (#struct){ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -5,6 +5,10 @@ expr.error2.a: conflicting values 4 and 3: ./in.cue:8:5 ./in.cue:9:5 +0: structural cycle: + ./in.cue:13:5 +1: structural cycle: + ./in.cue:17:5 Result: (_|_){ @@ -33,17 +37,15 @@ error1: (_|_){ // [structural cycle] a: (_|_){ - // [structural cycle] - 0: (string){ "1" } - 1: (string){ "2" } - } - } - error2: (_|_){ - // [structural cycle] - a: (_|_){ - // [structural cycle] - 0: (string){ "1" } - 1: (string){ "2" } + // [structural cycle] 0: structural cycle: + // ./in.cue:13:5 + } + } + error2: (_|_){ + // [structural cycle] + a: (_|_){ + // [structural cycle] 1: structural cycle: + // ./in.cue:17:5 } } } @@ -59,10 +61,7 @@ ok2: (struct){ Y: (struct){ } - a: (struct){ - b: (struct){ - } - } + a: ~(selfEmbed.ok2.x) x: (struct){ b: (struct){ } @@ -99,10 +98,7 @@ } Y: (struct){ } - a: (struct){ - b: (struct){ - } - } + a: ~(selfEmbed.ok6.x) } } disjSelf: (struct){ -- diff/todo/p3 -- list.error*: different error messages. -- out/eval -- Errors: expr.error1.a: conflicting values 4 and 3: ./in.cue:4:5 ./in.cue:5:5 expr.error2.a: conflicting values 4 and 3: ./in.cue:8:5 ./in.cue:9:5 Result: (_|_){ // [eval] expr: (_|_){ // [eval] error1: (_|_){ // [eval] a: (_|_){ // [eval] expr.error1.a: conflicting values 4 and 3: // ./in.cue:4:5 // ./in.cue:5:5 } } error2: (_|_){ // [eval] a: (_|_){ // [eval] expr.error2.a: conflicting values 4 and 3: // ./in.cue:8:5 // ./in.cue:9:5 } } } list: (_|_){ // [structural cycle] error1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (string){ "1" } 1: (string){ "2" } } } error2: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (string){ "1" } 1: (string){ "2" } } } } selfEmbed: (struct){ ok1: (struct){ a: (struct){ } Y: (struct){ } x: (struct){ } } ok2: (struct){ Y: (struct){ } a: (struct){ b: (struct){ } } x: (struct){ b: (struct){ } } } ok3: (struct){ Y: (struct){ } a: (struct){ } x: (struct){ } } ok4: (struct){ a: (struct){ } x: (struct){ } Y: (struct){ } } ok5: (struct){ x: (struct){ } a: (struct){ } Y: (struct){ } } ok6: (struct){ x: (struct){ b: (struct){ } } Y: (struct){ } a: (struct){ b: (struct){ } } } } disjSelf: (struct){ ok1: (struct){ #A: (_){ |((string){ string }, (_){ _ }) } x: (_){ |((string){ string }, (_){ _ }) } } ok2: (struct){ x: (_){ |((string){ string }, (_){ _ }) } #A: (_){ |((string){ string }, (_){ _ }) } } ok3: (struct){ #A: (_){ |((_){ _ }, (string){ string }) } x: (_){ |((_){ _ }, (string){ string }) } } ok4: (struct){ x: (_){ |((_){ _ }, (string){ string }) } #A: (_){ |((_){ _ }, (string){ string }) } } } disjEmbed: (struct){ ok1: (struct){ #A: ((string|struct)){ |((string){ string }, (#struct){ }) } x: ((string|struct)){ |((string){ string }, (#struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (#struct){ }) } #A: ((string|struct)){ |((string){ string }, (#struct){ }) } } ok3: (struct){ #A: ((string|struct)){ |((#struct){ }, (string){ string }) } x: ((string|struct)){ |((#struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((#struct){ }, (string){ string }) } #A: ((string|struct)){ |((#struct){ }, (string){ string }) } } } disjList: (struct){ ok1: (struct){ #A: (string){ string } x: (string){ string } y: (#list){ 0: (#list){ 0: (#list){ 0: (#list){ 0: (string){ string } } } } } } ok2: (struct){ x: (string){ string } #A: (string){ string } } ok3: (struct){ #A: (string){ string } x: (string){ string } } ok4: (struct){ x: (string){ string } #A: (string){ string } } } name: (string){ "foo" } dynamicSelf: (struct){ ok1: (struct){ x: (_){ |((string){ string }, (_){ _ }) } foo: (_){ |((string){ string }, (_){ _ }) } } ok2: (struct){ x: (_){ |((string){ string }, (_){ _ }) } foo: (_){ |((string){ string }, (_){ _ }) } } ok3: (struct){ x: (_){ |((_){ _ }, (string){ string }) } foo: (_){ |((_){ _ }, (string){ string }) } } ok4: (struct){ x: (_){ |((_){ _ }, (string){ string }) } foo: (_){ |((_){ _ }, (string){ string }) } } } dynamicEmbed: (struct){ ok1: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } foo: ((string|struct)){ |((string){ string }, (struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } foo: ((string|struct)){ |((string){ string }, (struct){ }) } } ok3: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } foo: ((string|struct)){ |((struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } foo: ((string|struct)){ |((struct){ }, (string){ string }) } } } dynamicList: (struct){ ok1: (struct){ x: (string){ string } y: (#list){ 0: (#list){ 0: (#list){ 0: (#list){ 0: (string){ string } } } } } foo: (string){ string } } ok2: (struct){ x: (string){ string } foo: (string){ string } } ok3: (struct){ x: (string){ string } foo: (string){ string } } ok4: (struct){ x: (string){ string } foo: (string){ string } } } dynamicPatternSelf: (struct){ ok1: (struct){ } ok2: (struct){ } } dynamicPatternEmbed: (struct){ ok1: (struct){ } ok2: (struct){ } } dynamicPatternList: (struct){ ok1: (struct){ } ok2: (struct){ } } valueSelf: (struct){ ok1: (struct){ y: ((string|struct)){ |((string){ string }, (struct){ }) } x: ((string|struct)){ |((string){ string }, (struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } y: ((string|struct)){ |((string){ string }, (struct){ }) } } ok3: (struct){ y: ((string|struct)){ |((struct){ }, (string){ string }) } x: ((string|struct)){ |((struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } y: ((string|struct)){ |((struct){ }, (string){ string }) } } } valueEmbed: (struct){ ok1: (struct){ y: ((string|struct)){ |((string){ string }, (struct){ }) } x: ((string|struct)){ |((string){ string }, (struct){ }) } } ok2: (struct){ x: ((string|struct)){ |((string){ string }, (struct){ }) } y: ((string|struct)){ |((string){ string }, (struct){ }) } } ok3: (struct){ y: ((string|struct)){ |((struct){ }, (string){ string }) } x: ((string|struct)){ |((struct){ }, (string){ string }) } } ok4: (struct){ x: ((string|struct)){ |((struct){ }, (string){ string }) } y: ((string|struct)){ |((struct){ }, (string){ string }) } } } valueList: (struct){ ok1: (struct){ y: (string){ string } x: (string){ string } } ok2: (struct){ x: (string){ string } y: (string){ string } } ok3: (struct){ y: (string){ string } x: (string){ string } } ok4: (struct){ x: (string){ string } y: (string){ string } } } issue1729: (struct){ t1: (struct){ #x: (#struct){ } x: (#struct){ } } t2: (struct){ x: (#struct){ } #x: (#struct){ } } } } -- out/compile -- --- in.cue { expr: { error1: { a: 3 a: (〈0;a〉 + 1) } } expr: { error2: { a: (〈0;a〉 + 1) a: 3 } } list: { error1: { a: [ "1", "2", ] a: 〈import;list〉.Concat([ 〈1;a〉, [ "3", ], ]) } } list: { error2: { a: 〈import;list〉.Concat([ [ "3", ], 〈1;a〉, ]) a: [ "1", "2", ] } } selfEmbed: { ok1: { a: 〈0;x〉 Y: 〈0;x〉 x: { 〈1;Y〉 } } } selfEmbed: { ok2: { Y: 〈0;x〉.b a: 〈0;x〉 x: { b: { 〈2;Y〉 } } } } selfEmbed: { ok3: { Y: 〈0;x〉 a: 〈0;x〉 x: { 〈1;Y〉 } } } selfEmbed: { ok4: { a: 〈0;x〉 x: { 〈1;Y〉 } Y: 〈0;x〉 } } selfEmbed: { ok5: { x: { 〈1;Y〉 } a: 〈0;x〉 Y: 〈0;x〉 } } selfEmbed: { ok6: { x: { b: { 〈2;Y〉 } } Y: 〈0;x〉.b a: 〈0;x〉 } } disjSelf: { ok1: { #A: (string|〈0;#A〉) x: 〈0;#A〉 } } disjSelf: { ok2: { x: 〈0;#A〉 #A: (string|〈0;#A〉) } } disjSelf: { ok3: { #A: (〈0;#A〉|string) x: 〈0;#A〉 } } disjSelf: { ok4: { x: 〈0;#A〉 #A: (〈0;#A〉|string) } } disjEmbed: { ok1: { #A: (string|{ 〈1;#A〉 }) x: 〈0;#A〉 } } disjEmbed: { ok2: { x: 〈0;#A〉 #A: (string|{ 〈1;#A〉 }) } } disjEmbed: { ok3: { #A: ({ 〈1;#A〉 }|string) x: 〈0;#A〉 } } disjEmbed: { ok4: { x: 〈0;#A〉 #A: ({ 〈1;#A〉 }|string) } } disjList: _ disjList: { ok1: { #A: (string|[ 〈1;#A〉, ]) x: 〈0;#A〉 y: 〈0;x〉 y: [ [ [ [ string, ], ], ], ] } } disjList: { ok2: { x: 〈0;#A〉 #A: (string|[ 〈1;#A〉, ]) } } disjList: { ok3: { #A: ([ 〈1;#A〉, ]|string) x: 〈0;#A〉 } } disjList: { ok4: { x: 〈0;#A〉 #A: ([ 〈1;#A〉, ]|string) } } name: "foo" dynamicSelf: { ok1: { 〈2;name〉: (string|〈0;(〈2;name〉)〉) x: 〈0;(〈2;name〉)〉 } } dynamicSelf: { ok2: { x: 〈0;(〈2;name〉)〉 〈2;name〉: (string|〈0;(〈2;name〉)〉) } } dynamicSelf: { ok3: { 〈2;name〉: (〈0;(〈2;name〉)〉|string) x: 〈0;(〈2;name〉)〉 } } dynamicSelf: { ok4: { x: 〈0;(〈2;name〉)〉 〈2;name〉: (〈0;(〈2;name〉)〉|string) } } dynamicEmbed: { ok1: { 〈2;name〉: (string|{ 〈1;(〈2;name〉)〉 }) x: 〈0;(〈2;name〉)〉 } } dynamicEmbed: { ok2: { x: 〈0;(〈2;name〉)〉 〈2;name〉: (string|{ 〈1;(〈2;name〉)〉 }) } } dynamicEmbed: { ok3: { 〈2;name〉: ({ 〈1;(〈2;name〉)〉 }|string) x: 〈0;(〈2;name〉)〉 } } dynamicEmbed: { ok4: { x: 〈0;(〈2;name〉)〉 〈2;name〉: ({ 〈1;(〈2;name〉)〉 }|string) } } dynamicList: _ dynamicList: { ok1: { 〈2;name〉: (string|[ 〈1;(〈2;name〉)〉, ]) x: 〈0;(〈2;name〉)〉 y: 〈0;x〉 y: [ [ [ [ string, ], ], ], ] } } dynamicList: { ok2: { x: 〈0;(〈2;name〉)〉 〈2;name〉: (string|[ 〈1;(〈2;name〉)〉, ]) } } dynamicList: { ok3: { 〈2;name〉: ([ 〈1;(〈2;name〉)〉, ]|string) x: 〈0;(〈2;name〉)〉 } } dynamicList: { ok4: { x: 〈0;(〈2;name〉)〉 〈2;name〉: ([ 〈1;(〈2;name〉)〉, ]|string) } } dynamicPatternSelf: { ok1: { [string]: (string|〈0;(〈0;-〉)〉) } } dynamicPatternSelf: { ok2: { [string]: (〈0;(〈0;-〉)〉|string) } } dynamicPatternEmbed: { ok1: { [string]: (string|{ 〈1;(〈0;-〉)〉 }) } } dynamicPatternEmbed: { ok2: { [string]: ({ 〈1;(〈0;-〉)〉 }|string) } } dynamicPatternList: { ok1: { [string]: (string|[ 〈1;(〈0;-〉)〉, ]) } } dynamicPatternList: { ok2: { [string]: ([ 〈1;(〈0;-〉)〉, ]|string) } } valueSelf: { ok1: { y: { (string|〈1〉) } x: 〈0;y〉 } } valueSelf: { ok2: { x: 〈0;y〉 y: { (string|〈1〉) } } } valueSelf: { ok3: { y: { (〈1〉|string) } x: 〈0;y〉 } } valueSelf: { ok4: { x: 〈0;y〉 y: { (〈1〉|string) } } } valueEmbed: { ok1: { y: { (string|{ 〈2〉 }) } x: 〈0;y〉 } } valueEmbed: { ok2: { x: 〈0;y〉 y: { (string|{ 〈2〉 }) } } } valueEmbed: { ok3: { y: { ({ 〈2〉 }|string) } x: 〈0;y〉 } } valueEmbed: { ok4: { x: 〈0;y〉 y: { ({ 〈2〉 }|string) } } } valueList: { ok1: { y: { (string|[ 〈2〉, ]) } x: 〈0;y〉 } } valueList: { ok2: { x: 〈0;y〉 y: { (string|[ 〈2〉, ]) } } } valueList: { ok3: { y: { ([ 〈2〉, ]|string) } x: 〈0;y〉 } } valueList: { ok4: { x: 〈0;y〉 y: { ([ 〈2〉, ]|string) } } } issue1729: { t1: { #x: { (〈1;#x〉|{}) } x: (〈0;#x〉 & {}) } } issue1729: { t2: { x: (〈0;#x〉 & {}) #x: { (〈1;#x〉|{}) } } } } cue-lang-cue-db9cc73/cue/testdata/cycle/structural.txtar000066400000000000000000003057131474664451600234710ustar00rootroot00000000000000-- in.cue -- import "list" a1: { f: [f] } a2: { f: f } a3: { f: {g: f} } a4: { a: [a | int] } a5: { a: b: a | int } a6: { a: a | int } a7: { a: c.x b: { x: c y: "foo" } c: { x: b.y y: 3 } } b1: { b: a & [1] a: [a | int] } b2: { a: [a | int] b: a & [1] } b3: { x: a: [a | int] b: x & {a: [1]} } b4: { b: x.y & [1] x: y: [y] } // Ensure that the cycle error is not blindly copied to a referring field, // as the cycle may not persist. b4: cond1: { b: x.y & { _z: false, [1] } x: y: { _z: *true | bool if _z { [y] } } } // This reports a structural cycle at b4.cond2.b, because the value it refers // has a structural cycle. Technically, this is incorrect, as the cycle // really only occurs in b4.cond2.x.y. But since structural cycles are // permanent, the entire configuration is invalidated, so the spurious // additional cycle is merely cosmetic. By most logical standards, one can prove // any fact from a contradiction. So assuming that, this is not incorrect. // TODO: fix this cosmetic blemish. b4: cond2: { x: y: { _z: *true | bool if _z { [y] } } b: x.y & { _z: false, [1] } } b5: { b: x.y & {a: [1]} x: y: a: [a | int] } b6: { b: x & {a: [1]} x: a: [a] } b7: { b: a & [[1]] a: [a] } // Issue #555 b8: { x: a a: f: b b: a | string } // Issue #555 b9: { #a: string | #b | #ref #b: { c: [#a, #a, #a] } #ref: ref: string x: #b | #ref } // Issue #534 // TODO: the resolution here is arguably incorrect: c should be // d: string | { b: string } // However, this is not the end of the world, as the disjunction is preserved // under the hood and still unifies with extended structure. b10: { a: close({ b: string | a | c }) c: close({ d: string | a }) d: d: b: string } // Issue #509 -- with comprehension b11: { #list: { tail: #list | *null if tail != null { } } } // Issue #509 -- with comprehension b12: { #list: { V=value: int T=tail: #list | *null if T != null { sum: V + T.sum } if T == null { sum: V } } list1: #list list1: { value: 1 tail: { value: 2 tail: { value: 3 tail: { value: 4 } } } } } // More trigger happy on stack overflows. b12b: { #list: { tail: #list if tail != null { sum: tail.sum } } list1: #list list1: { tail: { tail: { } } } } // Issue #587 b13: root: a: [for x in root {x}] // Issue #587 // TODO: this should probably be okay if we allow shallow evaluation of // comprehension sources. See #1881. b14: { root: { a: [...int] for x in a { "\(x)": {} } b: [for x in root {x}] } } // This is okay // Issue #587 b15: root: a: {for x in root {x}} // Issue #502 -- unused bulk constraints are not cyclic p1: { #T: { a: [string]: link: #T } a: #T & { a: one: link: a: two: {} } } // Issue #502 -- but they are if it is invoked within the struct. p2: { #T: { a: [string]: link: #T a: b: {} } a: #T & { a: one: link: a: two: {} } } // Issue #502 -- or added later. p3: { #S: #T: { a: [string]: link: #T } #U: { #S #T: a: b: {} } a: #U.#T & { a: one: link: a: two: {} } } // Issue #502 -- unused bulk constraints are not cyclic p4: { #T: { a: [...{link: #T}] } a: #T & { a: [{link: a: [{}]}] } } // Issue #502 -- but they are if it is invoked within the struct. p5: { #T: { a: [...{link: #T}] a: [{}] } a: #T & { a: [{link: a: [{}]}] } } // Issue #502 -- or added later. p6: { #S: #T: { a: [...{link: #T}] } #U: { #S #T: a: [{}] } a: #U.#T & { a: [{link: a: [{}]}] } } c1: { a: { b: {} c: a & b } } // indirection d1: { a: b: c: d: {h: int, t: r} r: a.b x: a.b.c } d2: { x: a.b.c r: a.b a: b: c: d: {h: int, t: r} } d3: { config: { a: b: c: indirect indirect: [a.b, null][i] i: int | *1 } x: config & {i: 0} } // Ensure that the cycles here fail early. // TODO: they can still be shorter. shortPathFail: _ shortPathFail: doubleRef: { // Avoid this: the first #List reference is different from the second, so // the second #List reference counts as a first occurrence, causing the // result to be longer than perhaps expected. a: #List #List: Next: #List | *null } shortPathFail: elipsis: { // Avoid this: the elipsis causes `_` to be mixed in with the #Foo // reference, causing the first cycle to be discounted. t1: { #Foo: ref: null | #Foo #Foo: { ... } } t2: { Foo: ref: Foo Foo: {...} } } patternFail: issue2374: { r=[string]: {b: r} a: {r: 0} } shortPathFail: comprehension: { #list: { tail: #list | *null if tail != null { } } } withLetFail: { schema: next: _schema_1 let _schema_1 = schema } fieldsSumInfinite: issue3310: { cheeseburger: 3.00 fries: 2.00 sprite: 1.00 total: list.Sum([for _, v in issue3310 {v}]) } listOptOK: { list: { head: int tail?: list } a: list & {head: 3, tail: head: 2} } // The cyclic definitions below used to work OK on old versions of evalv2, // and broke around the release of CUE v0.6.0. evalv3 fixes this again. // It should succeed, given that the optional field breaks the cycle. issue2545: { #A: { B?: #B } #B: { A: #A } } // combining structural with reference cycles e1: { a: a a: c: a b: c: b b: b } e2: { a: {a} a: c: a b: c: b b: {b} } e3: { a: [a] a: c: a b: [b] b: c: b } e4: { a: [a | {}] a: [[{c: 1}]] b: [[{c: 1}]] b: [b | {}] } e5: { a: c: a | int a: a | int b: b | int b: c: b | int } // validating values nestedList: { v1e: { x: [x | int, 1] y: x & [[[2], 1], 1] } v2e: { y: x & [[[2], 1], 1] x: [x | int, 1] } v1: { x: [x | int, 1] y: x & [[[2, 1], 1], 1] } v2: { y: x & [[[2, 1], 1], 1] x: [x | int, 1] } } v3: { list: { head: int tail: list | null } myList: list myList: { head: 2 tail: { head: 3 tail: { head: 4 } } } } v4: { list: { head: int tail: list | 1 } myList: list myList: { head: 2 tail: head: 3 } } v5: { list: { head: int tail: list | {} } myList: list myList: { head: 2 tail: head: 3 } } // Example from "The Logic of Type Feature Structures" (Bob Carpenter)/ z1: { y: { f: h: g g: _ } x: { f: _ g: f } z: x & y } // Cross references. Here there is no cycle, but the repeated instantiations // of T will cause, in turn, cause repeated resolution of `x`. The algorithm // should not identify these as cyclic references. Instead, it should be // noted that the reference is each time referring to new content. // Issue #754 crossRefNoCycle: t1: { T: { x: _ y: x } C: { x: T } & T } crossRefNoCycle: t2: { T: { x: _ y: x } C: T & { x: T } } crossRefNoCycle: t3: { T: { x: _ y: x z: y } C: T & { x: T } } crossRefNoCycle: t4: { T: { x: _ y: x z: y } C: T & { x: T & { x: T } } } crossRefNoCycle: t5: { T: X={ y: X.x } C: T & { x: T } } // Ensure these are NOT treated as structural errors. n1: a: b: int n2: n1 & {a: n1} n3: n1 & {n1} n4: n1 & {x: n1 & {y: n1 & {z: int}}} -- out/evalalpha/stats -- Leaks: 1795 Freed: 432 Reused: 432 Allocs: 1795 Retain: 0 Unifications: 1138 Conjuncts: 6059 Disjuncts: 1043 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 15 -Freed: 829 -Reused: 817 -Allocs: 27 -Retain: 64 +Leaks: 1795 +Freed: 432 +Reused: 432 +Allocs: 1795 +Retain: 0 -Unifications: 658 -Conjuncts: 1282 -Disjuncts: 880 +Unifications: 1138 +Conjuncts: 6059 +Disjuncts: 1043 -- out/eval/stats -- Leaks: 15 Freed: 835 Reused: 823 Allocs: 27 Retain: 66 Unifications: 664 Conjuncts: 1289 Disjuncts: 887 -- out/evalalpha -- Errors: a1.f.0: structural cycle a3.f.g: structural cycle b12b.#list.tail: structural cycle b13.root.a.0.0: structural cycle b14.root.b.1.1: structural cycle b4.b.0: conflicting values 1 and [y] (mismatched types int and list): ./in.cue:55:12 ./in.cue:56:8 b4.b.0.0: structural cycle b4.cond1.x.y.0: structural cycle b4.cond2.x.y.0: structural cycle b4.x.y.0: structural cycle b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): ./in.cue:94:13 ./in.cue:94:14 b6.b.a.0.0: structural cycle b6.x.a.0: structural cycle b7.a.0: structural cycle b7.b.0.0: conflicting values 1 and [a] (mismatched types int and list): ./in.cue:99:11 ./in.cue:100:5 b7.b.0.0.0: structural cycle c1.a.c.c: structural cycle d1.r: structural cycle d2.a.b.c.d.t: structural cycle d3.x.indirect: structural cycle e1.a.c: structural cycle e1.b.c: structural cycle e2.a.c: structural cycle e2.b.c: structural cycle e3.a: conflicting values [a] and {c:a} (mismatched types list and struct): ./in.cue:412:5 ./in.cue:413:5 e3.a.c: structural cycle e3.b: conflicting values [b] and {c:b} (mismatched types list and struct): ./in.cue:415:5 ./in.cue:416:5 e3.b.c: structural cycle e4.a.0: 10 errors in empty disjunction: e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:420:10 ./in.cue:421:6 e4.a.0.0: 8 errors in empty disjunction: e4.a.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): ./in.cue:421:6 ./in.cue:421:7 e4.a.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:420:10 ./in.cue:421:6 e4.a.0.0.0: 4 errors in empty disjunction: e4.a.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): ./in.cue:421:6 ./in.cue:421:7 e4.a.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:420:10 ./in.cue:421:6 e4.a.0.0.0: structural cycle e4.b.0: 10 errors in empty disjunction: e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:424:10 e4.b.0.0: 8 errors in empty disjunction: e4.b.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:423:7 e4.b.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:424:10 e4.b.0.0.0: 4 errors in empty disjunction: e4.b.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:423:7 e4.b.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:424:10 e4.b.0.0.0: structural cycle issue2545.#B.A: structural cycle nestedList.v1e.y.0: 4 errors in empty disjunction: nestedList.v1e.y.0: conflicting values [[2],1] and int (mismatched types list and int): ./in.cue:438:11 ./in.cue:439:11 nestedList.v1e.y.0.0: 2 errors in empty disjunction: nestedList.v1e.y.0.0: conflicting values [2] and int (mismatched types list and int): ./in.cue:438:11 ./in.cue:439:12 nestedList.v2e.y.0: 4 errors in empty disjunction: nestedList.v2e.y.0: conflicting values [[2],1] and int (mismatched types list and int): ./in.cue:443:11 ./in.cue:444:11 nestedList.v2e.y.0.0: 2 errors in empty disjunction: nestedList.v2e.y.0.0: conflicting values [2] and int (mismatched types list and int): ./in.cue:443:12 ./in.cue:444:11 p2.#T.a.b.link: structural cycle p3.#U.#T.a.b.link: structural cycle p5.#T.a.0.link: structural cycle p6.#U.#T.a.0.link: structural cycle patternFail.issue2374.a.b: structural cycle shortPathFail.elipsis.t2.Foo.ref: structural cycle withLetFail.schema.next: structural cycle z1.z.g.h: structural cycle 3: structural cycle: ./in.cue:371:9 e4.a.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: ./in.cue:421:11 ./in.cue:420:6 ./in.cue:421:6 ./in.cue:421:7 e4.a.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: ./in.cue:421:11 ./in.cue:420:6 ./in.cue:421:6 ./in.cue:421:7 e4.b.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: ./in.cue:423:11 ./in.cue:423:6 ./in.cue:423:7 ./in.cue:424:6 e4.b.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: ./in.cue:423:11 ./in.cue:423:6 ./in.cue:423:7 ./in.cue:424:6 nestedList.v1e.y.0.0: incompatible list lengths (1 and 2): ./in.cue:438:6 nestedList.v2e.y.0.0: incompatible list lengths (1 and 2): ./in.cue:444:6 Result: (_|_){ // [eval] a1: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] a1.f.0: structural cycle } } } a2: (struct){ f: (_){ _ } } a3: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] g: (_|_){ // [structural cycle] a3.f.g: structural cycle } } } a4: (struct){ a: (#list){ 0: (int){ int } } } a5: (struct){ a: (struct){ b: (int){ int } } } a6: (struct){ a: (_){ |((_){ _ }, (int){ int }) } } a7: (struct){ a: (string){ "foo" } b: (struct){ x: ~(a7.c) y: (string){ "foo" } } c: (struct){ x: (string){ "foo" } y: (int){ 3 } } } b1: (struct){ b: (#list){ 0: (int){ 1 } } a: (#list){ 0: (int){ int } } } b2: (struct){ a: (#list){ 0: (int){ int } } b: (#list){ 0: (int){ 1 } } } b3: (struct){ x: (struct){ a: (#list){ 0: (int){ int } } } b: (struct){ a: (#list){ 0: (int){ 1 } } } } b4: (_|_){ // [eval] b: (_|_){ // [eval] 0: (_|_){ // [eval] b4.b.0: conflicting values 1 and [y] (mismatched types int and list): // ./in.cue:55:12 // ./in.cue:56:8 // b4.b.0.0: structural cycle 0: (_|_){ // [structural cycle] b4.b.0.0: structural cycle } } } x: (_|_){ // [structural cycle] y: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b4.x.y.0: structural cycle } } } cond1: (_|_){ // [structural cycle] b: (#list){ _z: (bool){ false } 0: (int){ 1 } } x: (_|_){ // [structural cycle] y: (_|_){ // [structural cycle] _z: (bool){ |(*(bool){ true }, (bool){ bool }) } 0: (_|_){ // [structural cycle] b4.cond1.x.y.0: structural cycle } } } } cond2: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] y: (_|_){ // [structural cycle] _z: (bool){ |(*(bool){ true }, (bool){ bool }) } 0: (_|_){ // [structural cycle] b4.cond2.x.y.0: structural cycle } } } b: (_|_){ // [structural cycle] b4.cond2.x.y.0: structural cycle } } } b5: (struct){ b: (struct){ a: (#list){ 0: (int){ 1 } } } x: (struct){ y: (struct){ a: (#list){ 0: (int){ int } } } } } b6: (_|_){ // [eval] b: (_|_){ // [eval] a: (_|_){ // [eval] 0: (_|_){ // [eval] b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): // ./in.cue:94:13 // ./in.cue:94:14 // b6.b.a.0.0: structural cycle 0: (_|_){ // [structural cycle] b6.b.a.0.0: structural cycle } } } } x: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b6.x.a.0: structural cycle } } } } b7: (_|_){ // [eval] b: (_|_){ // [eval] 0: (_|_){ // [eval] 0: (_|_){ // [eval] b7.b.0.0: conflicting values 1 and [a] (mismatched types int and list): // ./in.cue:99:11 // ./in.cue:100:5 // b7.b.0.0.0: structural cycle 0: (_|_){ // [structural cycle] b7.b.0.0.0: structural cycle } } } } a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b7.a.0: structural cycle } } } b8: (struct){ x: ~(b8.a) a: (struct){ f: (string){ string } } b: (string){ string } } b9: (struct){ #a: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } #b: (#struct){ c: (#list){ 0: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 1: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 2: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } } } #ref: (#struct){ ref: (string){ string } } x: (struct){ |((#struct){ c: (#list){ 0: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 1: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 2: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } } }, (#struct){ ref: (string){ string } }) } } b10: (struct){ a: (#struct){ b: ((string|struct)){ |((string){ string }, (#struct){ d: (string){ string } }) } } c: (#struct){ d: ((string|struct)){ |((string){ string }, (#struct){ b: ((string|struct)){ |((string){ string }, (#struct){ b: ((string|struct)){ |((string){ string }, (#struct){ b: (string){ string } }) } }) } }) } } d: (struct){ d: (struct){ b: (string){ string } } } } b11: (struct){ #list: (#struct){ tail: (null){ null } } } b12: (struct){ #list: (#struct){ value: (int){ int } tail: (null){ null } sum: (int){ int } } list1: (#struct){ value: (int){ 1 } tail: (#struct){ value: (int){ 2 } tail: (#struct){ value: (int){ 3 } tail: (#struct){ value: (int){ 4 } tail: ((null|struct)){ |(*(null){ null }, (#struct){ value: (int){ int } tail: (null){ null } sum: (int){ int } }) } sum: (int){ 4 } } sum: (int){ 7 } } sum: (int){ 9 } } sum: (int){ 10 } } } b12b: (_|_){ // [structural cycle] #list: (_|_){ // [structural cycle] b12b.#list.tail: structural cycle } list1: (_|_){ // [structural cycle] b12b.#list.tail: structural cycle } } b13: (_|_){ // [structural cycle] root: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b13.root.a.0.0: structural cycle } } } } } b14: (_|_){ // [structural cycle] root: (_|_){ // [structural cycle] a: (list){ } b: (_|_){ // [structural cycle] 0: (list){ } 1: (_|_){ // [structural cycle] 0: (list){ } 1: (_|_){ // [structural cycle] b14.root.b.1.1: structural cycle } } } } } b15: (struct){ root: (struct){ a: (struct){ } } } p1: (struct){ #T: (#struct){ a: (#struct){ } } a: (#struct){ a: (#struct){ one: (#struct){ link: (#struct){ a: (#struct){ two: (#struct){ link: ~(p1.#T) } } } } } } } p2: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p2.#T.a.b.link: structural cycle } } } } a: (_|_){ // [structural cycle] a: (struct){ one: (struct){ link: (struct){ a: (struct){ two: (struct){ } } } } } } } p3: (_|_){ // [structural cycle] #S: (#struct){ #T: (#struct){ a: (#struct){ } } } #U: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p3.#U.#T.a.b.link: structural cycle } } } } } a: (_|_){ // [structural cycle] p3.#U.#T.a.b.link: structural cycle } } p4: (struct){ #T: (#struct){ a: (list){ } } a: (#struct){ a: (#list){ 0: (#struct){ link: (#struct){ a: (#list){ 0: (#struct){ link: ~(p4.#T) } } } } } } } p5: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p5.#T.a.0.link: structural cycle } } } } a: (_|_){ // [structural cycle] a: (#list){ 0: (struct){ link: (struct){ a: (#list){ 0: (struct){ } } } } } } } p6: (_|_){ // [structural cycle] #S: (#struct){ #T: (#struct){ a: (list){ } } } #U: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p6.#U.#T.a.0.link: structural cycle } } } } } a: (_|_){ // [structural cycle] p6.#U.#T.a.0.link: structural cycle } } c1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (struct){ } c: (_|_){ // [structural cycle] b: (struct){ } c: (_|_){ // [structural cycle] c1.a.c.c: structural cycle } } } } d1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] h: (int){ int } t: (_|_){ // [structural cycle] d1.r: structural cycle } } } } } r: (_|_){ // [structural cycle] d1.r: structural cycle } x: (_|_){ // [structural cycle] d1.r: structural cycle } } d2: (_|_){ // [structural cycle] x: ~(d2.a.b.c) r: ~(d2.a.b) a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] h: (int){ int } t: (_|_){ // [structural cycle] d2.a.b.c.d.t: structural cycle } } } } } } d3: (_|_){ // [structural cycle] config: (struct){ a: (struct){ b: (struct){ c: (null){ null } } } indirect: (null){ null } i: (int){ |(*(int){ 1 }, (int){ int }) } } x: (_|_){ // [structural cycle] i: (int){ 0 } a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] d3.x.indirect: structural cycle } } } indirect: (_|_){ // [structural cycle] d3.x.indirect: structural cycle } } } shortPathFail: (_|_){ // [structural cycle] doubleRef: (struct){ a: ~(shortPathFail.doubleRef.#List) #List: (#struct){ Next: (null){ null } } } elipsis: (_|_){ // [structural cycle] t1: (struct){ #Foo: (#struct){ ref: (null){ null } } } t2: (_|_){ // [structural cycle] Foo: (_|_){ // [structural cycle] ref: (_|_){ // [structural cycle] shortPathFail.elipsis.t2.Foo.ref: structural cycle } } } } comprehension: (struct){ #list: (#struct){ tail: (null){ null } } } } patternFail: (_|_){ // [structural cycle] issue2374: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] r: (int){ 0 } b: (_|_){ // [structural cycle] patternFail.issue2374.a.b: structural cycle } } } } withLetFail: (_|_){ // [structural cycle] schema: (_|_){ // [structural cycle] next: (_|_){ // [structural cycle] withLetFail.schema.next: structural cycle } } let _schema_1#1 = (_|_){ // [structural cycle] withLetFail._schema_1: structural cycle } } fieldsSumInfinite: (_|_){ // [structural cycle] issue3310: (_|_){ // [structural cycle] cheeseburger: (float){ 3.00 } fries: (float){ 2.00 } sprite: (float){ 1.00 } total: (_|_){ // [structural cycle] 3: structural cycle: // ./in.cue:371:9 } } } listOptOK: (struct){ list: (struct){ head: (int){ int } tail?: (_|_){ // [structural cycle] listOptOK.list.tail: structural cycle } } a: (struct){ head: (int){ 3 } tail: (struct){ head: (int){ 2 } tail?: ~(listOptOK.list) } } } issue2545: (_|_){ // [structural cycle] #A: (#struct){ B?: ~(issue2545.#B) } #B: (_|_){ // [structural cycle] A: (_|_){ // [structural cycle] issue2545.#B.A: structural cycle } } } e1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e1.a.c: structural cycle } } b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e1.b.c: structural cycle } } } e2: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e2.a.c: structural cycle } } b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e2.b.c: structural cycle } } } e3: (_|_){ // [eval] a: (_|_){ // [eval] e3.a: conflicting values [a] and {c:a} (mismatched types list and struct): // ./in.cue:412:5 // ./in.cue:413:5 // e3.a.c: structural cycle c: (_|_){ // [structural cycle] e3.a.c: structural cycle } 0: (_|_){ // [structural cycle] e3.a.0: structural cycle } } b: (_|_){ // [eval] e3.b: conflicting values [b] and {c:b} (mismatched types list and struct): // ./in.cue:415:5 // ./in.cue:416:5 // e3.b.c: structural cycle c: (_|_){ // [structural cycle] e3.b.c: structural cycle } 0: (_|_){ // [structural cycle] e3.b.0: structural cycle } } } e4: (_|_){ // [eval] a: (_|_){ // [eval] 0: (_|_){ // [eval] e4.a.0: 10 errors in empty disjunction: // e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:420:10 // ./in.cue:421:6 // e4.a.0.0: 8 errors in empty disjunction: // e4.a.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): // ./in.cue:421:6 // ./in.cue:421:7 // e4.a.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:420:10 // ./in.cue:421:6 // e4.a.0.0.0: 4 errors in empty disjunction: // e4.a.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): // ./in.cue:421:6 // ./in.cue:421:7 // e4.a.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:420:10 // ./in.cue:421:6 // e4.a.0.0.0: structural cycle // e4.a.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: // ./in.cue:421:11 // ./in.cue:420:6 // ./in.cue:421:6 // ./in.cue:421:7 // e4.a.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: // ./in.cue:421:11 // ./in.cue:420:6 // ./in.cue:421:6 // ./in.cue:421:7 0: (struct){ c: (int){ 1 } } } } b: (_|_){ // [eval] 0: (_|_){ // [eval] e4.b.0: 10 errors in empty disjunction: // e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:424:10 // e4.b.0.0: 8 errors in empty disjunction: // e4.b.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:423:7 // e4.b.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:424:10 // e4.b.0.0.0: 4 errors in empty disjunction: // e4.b.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:423:7 // e4.b.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:424:10 // e4.b.0.0.0: structural cycle // e4.b.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: // ./in.cue:423:11 // ./in.cue:423:6 // ./in.cue:423:7 // ./in.cue:424:6 // e4.b.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: // ./in.cue:423:11 // ./in.cue:423:6 // ./in.cue:423:7 // ./in.cue:424:6 0: (struct){ c: (int){ 1 } } } } } e5: (struct){ a: (struct){ c: (int){ int } } b: (struct){ c: (int){ int } } } nestedList: (_|_){ // [eval] v1e: (_|_){ // [eval] x: (#list){ 0: (int){ int } 1: (int){ 1 } } y: (_|_){ // [eval] 0: (_|_){ // [eval] nestedList.v1e.y.0: 4 errors in empty disjunction: // nestedList.v1e.y.0: conflicting values [[2],1] and int (mismatched types list and int): // ./in.cue:438:11 // ./in.cue:439:11 // nestedList.v1e.y.0.0: 2 errors in empty disjunction: // nestedList.v1e.y.0.0: conflicting values [2] and int (mismatched types list and int): // ./in.cue:438:11 // ./in.cue:439:12 // nestedList.v1e.y.0.0: incompatible list lengths (1 and 2): // ./in.cue:438:6 0: (list){ list } 1: (int){ 1 } } 1: (int){ 1 } } } v2e: (_|_){ // [eval] y: (_|_){ // [eval] 0: (_|_){ // [eval] nestedList.v2e.y.0: 4 errors in empty disjunction: // nestedList.v2e.y.0: conflicting values [[2],1] and int (mismatched types list and int): // ./in.cue:443:11 // ./in.cue:444:11 // nestedList.v2e.y.0.0: 2 errors in empty disjunction: // nestedList.v2e.y.0.0: conflicting values [2] and int (mismatched types list and int): // ./in.cue:443:12 // ./in.cue:444:11 // nestedList.v2e.y.0.0: incompatible list lengths (1 and 2): // ./in.cue:444:6 0: (list){ list } 1: (int){ 1 } } 1: (int){ 1 } } x: (#list){ 0: (int){ int } 1: (int){ 1 } } } v1: (struct){ x: (#list){ 0: (int){ int } 1: (int){ 1 } } y: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 2 } 1: (int){ 1 } } 1: (int){ 1 } } 1: (int){ 1 } } } v2: (struct){ y: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 2 } 1: (int){ 1 } } 1: (int){ 1 } } 1: (int){ 1 } } x: (#list){ 0: (int){ int } 1: (int){ 1 } } } } v3: (struct){ list: (struct){ head: (int){ int } tail: (null){ null } } myList: (struct){ head: (int){ 2 } tail: (struct){ head: (int){ 3 } tail: (struct){ head: (int){ 4 } tail: ((null|struct)){ |((struct){ head: (int){ int } tail: (null){ null } }, (null){ null }) } } } } } v4: (struct){ list: (struct){ head: (int){ int } tail: (int){ 1 } } myList: (struct){ head: (int){ 2 } tail: (struct){ head: (int){ 3 } tail: ((int|struct)){ |((struct){ head: (int){ int } tail: (int){ 1 } }, (int){ 1 }) } } } } v5: (struct){ list: (struct){ head: (int){ int } tail: (struct){ } } myList: (struct){ head: (int){ 2 } tail: (struct){ |((struct){ head: (int){ 3 } tail: (struct){ |((struct){ head: (int){ int } tail: (struct){ } }, (struct){ }) } }, (struct){ head: (int){ 3 } }) } } } z1: (_|_){ // [structural cycle] y: (struct){ f: (struct){ h: (_){ _ } } g: (_){ _ } } x: (struct){ f: (_){ _ } g: (_){ _ } } z: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] h: ~(z1.z.g) } g: (_|_){ // [structural cycle] h: (_|_){ // [structural cycle] z1.z.g.h: structural cycle } } } } crossRefNoCycle: (struct){ t1: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } } C: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } } y: ~(crossRefNoCycle.t1.C.x) } } t2: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } } C: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } } y: ~(crossRefNoCycle.t2.C.x) } } t3: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } C: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } y: ~(crossRefNoCycle.t3.C.x) z: ~(crossRefNoCycle.t3.C.x) } } t4: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } C: (struct){ x: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } y: ~(crossRefNoCycle.t4.C.x.x) z: ~(crossRefNoCycle.t4.C.x.x) } y: ~(crossRefNoCycle.t4.C.x) z: ~(crossRefNoCycle.t4.C.x) } } t5: (struct){ T: (struct){ y: (_|_){ // [incomplete] crossRefNoCycle.t5.T.y: undefined field: x: // ./in.cue:556:8 } } C: (struct){ x: ~(crossRefNoCycle.t5.T) y: ~(crossRefNoCycle.t5.T) } } } n1: (struct){ a: (struct){ b: (int){ int } } } n2: (struct){ a: (struct){ b: (int){ int } a: (struct){ b: (int){ int } } } } n3: (struct){ a: (struct){ b: (int){ int } } } n4: (struct){ x: (struct){ y: (struct){ z: (int){ int } a: (struct){ b: (int){ int } } } a: (struct){ b: (int){ int } } } a: (struct){ b: (int){ int } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,22 +4,27 @@ b12b.#list.tail: structural cycle b13.root.a.0.0: structural cycle b14.root.b.1.1: structural cycle +b4.b.0: conflicting values 1 and [y] (mismatched types int and list): + ./in.cue:55:12 + ./in.cue:56:8 +b4.b.0.0: structural cycle b4.cond1.x.y.0: structural cycle b4.cond2.x.y.0: structural cycle b4.x.y.0: structural cycle b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): - ./in.cue:94:5 ./in.cue:94:13 ./in.cue:94:14 - ./in.cue:95:9 b6.b.a.0.0: structural cycle b6.x.a.0: structural cycle b7.a.0: structural cycle +b7.b.0.0: conflicting values 1 and [a] (mismatched types int and list): + ./in.cue:99:11 + ./in.cue:100:5 +b7.b.0.0.0: structural cycle c1.a.c.c: structural cycle -d1.a.b.c.d.t: structural cycle +d1.r: structural cycle d2.a.b.c.d.t: structural cycle -d2.r.c.d.t: structural cycle -d3.x.a.b.c: structural cycle +d3.x.indirect: structural cycle e1.a.c: structural cycle e1.b.c: structural cycle e2.a.c: structural cycle @@ -32,62 +37,95 @@ ./in.cue:415:5 ./in.cue:416:5 e3.b.c: structural cycle -e4.a.0: 4 errors in empty disjunction: +e4.a.0: 10 errors in empty disjunction: e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:420:10 ./in.cue:421:6 -e4.a.0.0: 2 errors in empty disjunction: -e4.a.0.0: conflicting values [[{c:1}]] and {c:1} (mismatched types list and struct): - ./in.cue:421:5 +e4.a.0.0: 8 errors in empty disjunction: +e4.a.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + ./in.cue:421:6 ./in.cue:421:7 e4.a.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): - ./in.cue:420:6 - ./in.cue:420:10 - ./in.cue:421:6 -e4.b.0: 4 errors in empty disjunction: + ./in.cue:420:10 + ./in.cue:421:6 +e4.a.0.0.0: 4 errors in empty disjunction: +e4.a.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + ./in.cue:421:6 + ./in.cue:421:7 +e4.a.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): + ./in.cue:420:10 + ./in.cue:421:6 +e4.a.0.0.0: structural cycle +e4.b.0: 10 errors in empty disjunction: e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:424:10 -e4.b.0.0: 2 errors in empty disjunction: -e4.b.0.0: conflicting values [(b|{})] and {c:1} (mismatched types list and struct): - ./in.cue:423:7 - ./in.cue:424:5 +e4.b.0.0: 8 errors in empty disjunction: +e4.b.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + ./in.cue:423:6 + ./in.cue:423:7 e4.b.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 - ./in.cue:424:6 - ./in.cue:424:10 + ./in.cue:424:10 +e4.b.0.0.0: 4 errors in empty disjunction: +e4.b.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + ./in.cue:423:6 + ./in.cue:423:7 +e4.b.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): + ./in.cue:423:6 + ./in.cue:424:10 +e4.b.0.0.0: structural cycle issue2545.#B.A: structural cycle nestedList.v1e.y.0: 4 errors in empty disjunction: -nestedList.v1e.y.0: conflicting values int and [[2],1] (mismatched types int and list): +nestedList.v1e.y.0: conflicting values [[2],1] and int (mismatched types list and int): ./in.cue:438:11 ./in.cue:439:11 nestedList.v1e.y.0.0: 2 errors in empty disjunction: -nestedList.v1e.y.0.0: conflicting values int and [2] (mismatched types int and list): +nestedList.v1e.y.0.0: conflicting values [2] and int (mismatched types list and int): ./in.cue:438:11 ./in.cue:439:12 -nestedList.v1e.y.0.0: incompatible list lengths (1 and 2) nestedList.v2e.y.0: 4 errors in empty disjunction: -nestedList.v2e.y.0: conflicting values int and [[2],1] (mismatched types int and list): +nestedList.v2e.y.0: conflicting values [[2],1] and int (mismatched types list and int): ./in.cue:443:11 ./in.cue:444:11 nestedList.v2e.y.0.0: 2 errors in empty disjunction: -nestedList.v2e.y.0.0: conflicting values int and [2] (mismatched types int and list): +nestedList.v2e.y.0.0: conflicting values [2] and int (mismatched types list and int): ./in.cue:443:12 ./in.cue:444:11 -nestedList.v2e.y.0.0: incompatible list lengths (1 and 2) p2.#T.a.b.link: structural cycle p3.#U.#T.a.b.link: structural cycle p5.#T.a.0.link: structural cycle p6.#U.#T.a.0.link: structural cycle patternFail.issue2374.a.b: structural cycle -shortPathFail.elipsis.t2.Foo.ref.ref: structural cycle +shortPathFail.elipsis.t2.Foo.ref: structural cycle withLetFail.schema.next: structural cycle -z1.z.f.h: structural cycle z1.z.g.h: structural cycle -d1.r: structural cycle: - ./in.cue:301:26 -d3.x.indirect: structural cycle: - ./in.cue:316:12 +3: structural cycle: + ./in.cue:371:9 +e4.a.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + ./in.cue:421:11 + ./in.cue:420:6 + ./in.cue:421:6 + ./in.cue:421:7 +e4.a.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + ./in.cue:421:11 + ./in.cue:420:6 + ./in.cue:421:6 + ./in.cue:421:7 +e4.b.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + ./in.cue:423:11 + ./in.cue:423:6 + ./in.cue:423:7 + ./in.cue:424:6 +e4.b.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + ./in.cue:423:11 + ./in.cue:423:6 + ./in.cue:423:7 + ./in.cue:424:6 +nestedList.v1e.y.0.0: incompatible list lengths (1 and 2): + ./in.cue:438:6 +nestedList.v2e.y.0.0: incompatible list lengths (1 and 2): + ./in.cue:444:6 Result: (_|_){ @@ -129,10 +167,7 @@ a7: (struct){ a: (string){ "foo" } b: (struct){ - x: (struct){ - x: (string){ "foo" } - y: (int){ 3 } - } + x: ~(a7.c) y: (string){ "foo" } } c: (struct){ @@ -169,11 +204,17 @@ } } b4: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] - 0: (_|_){ - // [structural cycle] b4.x.y.0: structural cycle + // [eval] + b: (_|_){ + // [eval] + 0: (_|_){ + // [eval] b4.b.0: conflicting values 1 and [y] (mismatched types int and list): + // ./in.cue:55:12 + // ./in.cue:56:8 + // b4.b.0.0: structural cycle + 0: (_|_){ + // [structural cycle] b4.b.0.0: structural cycle + } } } x: (_|_){ @@ -241,10 +282,9 @@ // [eval] 0: (_|_){ // [eval] b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): - // ./in.cue:94:5 // ./in.cue:94:13 // ./in.cue:94:14 - // ./in.cue:95:9 + // b6.b.a.0.0: structural cycle 0: (_|_){ // [structural cycle] b6.b.a.0.0: structural cycle } @@ -262,11 +302,20 @@ } } b7: (_|_){ - // [structural cycle] - b: (_|_){ - // [structural cycle] - 0: (_|_){ - // [structural cycle] b7.a.0: structural cycle + // [eval] + b: (_|_){ + // [eval] + 0: (_|_){ + // [eval] + 0: (_|_){ + // [eval] b7.b.0.0: conflicting values 1 and [a] (mismatched types int and list): + // ./in.cue:99:11 + // ./in.cue:100:5 + // b7.b.0.0.0: structural cycle + 0: (_|_){ + // [structural cycle] b7.b.0.0.0: structural cycle + } + } } } a: (_|_){ @@ -277,9 +326,7 @@ } } b8: (struct){ - x: (struct){ - f: (string){ string } - } + x: ~(b8.a) a: (struct){ f: (string){ string } } @@ -305,7 +352,7 @@ #ref: (#struct){ ref: (string){ string } } - x: (#struct){ |((#struct){ + x: (struct){ |((#struct){ c: (#list){ 0: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } @@ -328,7 +375,13 @@ }) } } c: (#struct){ - d: (string){ string } + d: ((string|struct)){ |((string){ string }, (#struct){ + b: ((string|struct)){ |((string){ string }, (#struct){ + b: ((string|struct)){ |((string){ string }, (#struct){ + b: (string){ string } + }) } + }) } + }) } } d: (struct){ d: (struct){ @@ -338,9 +391,7 @@ } b11: (struct){ #list: (#struct){ - tail: ((null|struct)){ |(*(null){ null }, (#struct){ - tail: (null){ null } - }) } + tail: (null){ null } } } b12: (struct){ @@ -357,7 +408,11 @@ value: (int){ 3 } tail: (#struct){ value: (int){ 4 } - tail: (null){ null } + tail: ((null|struct)){ |(*(null){ null }, (#struct){ + value: (int){ int } + tail: (null){ null } + sum: (int){ int } + }) } sum: (int){ 4 } } sum: (int){ 7 } @@ -429,10 +484,7 @@ link: (#struct){ a: (#struct){ two: (#struct){ - link: (#struct){ - a: (#struct){ - } - } + link: ~(p1.#T) } } } @@ -506,10 +558,7 @@ link: (#struct){ a: (#list){ 0: (#struct){ - link: (#struct){ - a: (list){ - } - } + link: ~(p4.#T) } } } @@ -600,47 +649,27 @@ // [structural cycle] h: (int){ int } t: (_|_){ - // [structural cycle] d1.a.b.c.d.t: structural cycle - } - } - } - } - } - r: (_|_){ - // [structural cycle] d1.r: structural cycle: - // ./in.cue:301:26 - } - x: (_|_){ - // [structural cycle] d1.a.b.c.d.t: structural cycle + // [structural cycle] d1.r: structural cycle + } + } + } + } + } + r: (_|_){ + // [structural cycle] d1.r: structural cycle + } + x: (_|_){ + // [structural cycle] d1.r: structural cycle } } d2: (_|_){ // [structural cycle] - x: (_|_){ - // [structural cycle] - d: (_|_){ - // [structural cycle] - h: (int){ int } - t: (_|_){ - // [structural cycle] - } - } - } - r: (_|_){ - // [structural cycle] - c: (_|_){ - // [structural cycle] - d: (_|_){ - // [structural cycle] - h: (int){ int } - t: (_|_){ - // [structural cycle] d2.r.c.d.t: structural cycle - } - } - } - } - a: (struct){ - b: (struct){ + x: ~(d2.a.b.c) + r: ~(d2.a.b) + a: (_|_){ + // [structural cycle] + b: (_|_){ + // [structural cycle] c: (_|_){ // [structural cycle] d: (_|_){ @@ -667,28 +696,25 @@ } x: (_|_){ // [structural cycle] + i: (int){ 0 } a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ - // [structural cycle] d3.x.a.b.c: structural cycle + // [structural cycle] d3.x.indirect: structural cycle } } } indirect: (_|_){ - // [structural cycle] d3.x.indirect: structural cycle: - // ./in.cue:316:12 - } - i: (int){ 0 } + // [structural cycle] d3.x.indirect: structural cycle + } } } shortPathFail: (_|_){ // [structural cycle] doubleRef: (struct){ - a: (#struct){ - Next: (null){ null } - } + a: ~(shortPathFail.doubleRef.#List) #List: (#struct){ Next: (null){ null } } @@ -697,9 +723,7 @@ // [structural cycle] t1: (struct){ #Foo: (#struct){ - ref: ((null|struct)){ |((null){ null }, (#struct){ - ref: (null){ null } - }) } + ref: (null){ null } } } t2: (_|_){ @@ -707,10 +731,7 @@ Foo: (_|_){ // [structural cycle] ref: (_|_){ - // [structural cycle] - ref: (_|_){ - // [structural cycle] shortPathFail.elipsis.t2.Foo.ref.ref: structural cycle - } + // [structural cycle] shortPathFail.elipsis.t2.Foo.ref: structural cycle } } } @@ -717,9 +738,7 @@ } comprehension: (struct){ #list: (#struct){ - tail: ((null|struct)){ |(*(null){ null }, (#struct){ - tail: (null){ null } - }) } + tail: (null){ null } } } } @@ -745,8 +764,7 @@ } } let _schema_1#1 = (_|_){ - // [structural cycle] withLetFail._schema_1: structural cycle: - // ./in.cue:362:17 + // [structural cycle] withLetFail._schema_1: structural cycle } } fieldsSumInfinite: (_|_){ @@ -757,7 +775,8 @@ fries: (float){ 2.00 } sprite: (float){ 1.00 } total: (_|_){ - // [structural cycle] + // [structural cycle] 3: structural cycle: + // ./in.cue:371:9 } } } @@ -772,9 +791,7 @@ head: (int){ 3 } tail: (struct){ head: (int){ 2 } - tail?: (_|_){ - // [structural cycle] listOptOK.a.tail.tail: structural cycle - } + tail?: ~(listOptOK.list) } } } @@ -781,12 +798,7 @@ issue2545: (_|_){ // [structural cycle] #A: (#struct){ - B?: (_|_){ - // [structural cycle] - A: (_|_){ - // [structural cycle] issue2545.#A.B.A: structural cycle - } - } + B?: ~(issue2545.#B) } #B: (_|_){ // [structural cycle] @@ -831,11 +843,12 @@ // [eval] e3.a: conflicting values [a] and {c:a} (mismatched types list and struct): // ./in.cue:412:5 // ./in.cue:413:5 - c: (_|_){ - // [structural cycle] e3.a.c: structural cycle - } - 0: (_|_){ - // [structural cycle] e3.a.c: structural cycle + // e3.a.c: structural cycle + c: (_|_){ + // [structural cycle] e3.a.c: structural cycle + } + 0: (_|_){ + // [structural cycle] e3.a.0: structural cycle } } b: (_|_){ @@ -842,11 +855,12 @@ // [eval] e3.b: conflicting values [b] and {c:b} (mismatched types list and struct): // ./in.cue:415:5 // ./in.cue:416:5 - c: (_|_){ - // [structural cycle] e3.b.c: structural cycle - } - 0: (_|_){ - // [structural cycle] e3.b.c: structural cycle + // e3.b.c: structural cycle + c: (_|_){ + // [structural cycle] e3.b.c: structural cycle + } + 0: (_|_){ + // [structural cycle] e3.b.0: structural cycle } } } @@ -855,38 +869,72 @@ a: (_|_){ // [eval] 0: (_|_){ - // [eval] e4.a.0: 4 errors in empty disjunction: + // [eval] e4.a.0: 10 errors in empty disjunction: // e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:420:10 // ./in.cue:421:6 - // e4.a.0.0: 2 errors in empty disjunction: - // e4.a.0.0: conflicting values [[{c:1}]] and {c:1} (mismatched types list and struct): - // ./in.cue:421:5 + // e4.a.0.0: 8 errors in empty disjunction: + // e4.a.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + // ./in.cue:421:6 // ./in.cue:421:7 // e4.a.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): - // ./in.cue:420:6 - // ./in.cue:420:10 - // ./in.cue:421:6 - 0: (struct){ - c: (int){ 1 } - } - } - } - b: (_|_){ - // [eval] - 0: (_|_){ - // [eval] e4.b.0: 4 errors in empty disjunction: + // ./in.cue:420:10 + // ./in.cue:421:6 + // e4.a.0.0.0: 4 errors in empty disjunction: + // e4.a.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + // ./in.cue:421:6 + // ./in.cue:421:7 + // e4.a.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): + // ./in.cue:420:10 + // ./in.cue:421:6 + // e4.a.0.0.0: structural cycle + // e4.a.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + // ./in.cue:421:11 + // ./in.cue:420:6 + // ./in.cue:421:6 + // ./in.cue:421:7 + // e4.a.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + // ./in.cue:421:11 + // ./in.cue:420:6 + // ./in.cue:421:6 + // ./in.cue:421:7 + 0: (struct){ + c: (int){ 1 } + } + } + } + b: (_|_){ + // [eval] + 0: (_|_){ + // [eval] e4.b.0: 10 errors in empty disjunction: // e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:424:10 - // e4.b.0.0: 2 errors in empty disjunction: - // e4.b.0.0: conflicting values [(b|{})] and {c:1} (mismatched types list and struct): - // ./in.cue:423:7 - // ./in.cue:424:5 + // e4.b.0.0: 8 errors in empty disjunction: + // e4.b.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + // ./in.cue:423:6 + // ./in.cue:423:7 // e4.b.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 - // ./in.cue:424:6 - // ./in.cue:424:10 + // ./in.cue:424:10 + // e4.b.0.0.0: 4 errors in empty disjunction: + // e4.b.0.0.0: conflicting values [{c:1}] and {c:1} (mismatched types list and struct): + // ./in.cue:423:6 + // ./in.cue:423:7 + // e4.b.0.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): + // ./in.cue:423:6 + // ./in.cue:424:10 + // e4.b.0.0.0: structural cycle + // e4.b.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + // ./in.cue:423:11 + // ./in.cue:423:6 + // ./in.cue:423:7 + // ./in.cue:424:6 + // e4.b.0.0.0: cannot combine regular field "c" with [1,_|_(cycle error)]: + // ./in.cue:423:11 + // ./in.cue:423:6 + // ./in.cue:423:7 + // ./in.cue:424:6 0: (struct){ c: (int){ 1 } } @@ -913,17 +961,16 @@ // [eval] 0: (_|_){ // [eval] nestedList.v1e.y.0: 4 errors in empty disjunction: - // nestedList.v1e.y.0: conflicting values int and [[2],1] (mismatched types int and list): + // nestedList.v1e.y.0: conflicting values [[2],1] and int (mismatched types list and int): // ./in.cue:438:11 // ./in.cue:439:11 // nestedList.v1e.y.0.0: 2 errors in empty disjunction: - // nestedList.v1e.y.0.0: conflicting values int and [2] (mismatched types int and list): + // nestedList.v1e.y.0.0: conflicting values [2] and int (mismatched types list and int): // ./in.cue:438:11 // ./in.cue:439:12 - // nestedList.v1e.y.0.0: incompatible list lengths (1 and 2) - 0: (#list){ - 0: (int){ 2 } - } + // nestedList.v1e.y.0.0: incompatible list lengths (1 and 2): + // ./in.cue:438:6 + 0: (list){ list } 1: (int){ 1 } } 1: (int){ 1 } @@ -935,17 +982,16 @@ // [eval] 0: (_|_){ // [eval] nestedList.v2e.y.0: 4 errors in empty disjunction: - // nestedList.v2e.y.0: conflicting values int and [[2],1] (mismatched types int and list): + // nestedList.v2e.y.0: conflicting values [[2],1] and int (mismatched types list and int): // ./in.cue:443:11 // ./in.cue:444:11 // nestedList.v2e.y.0.0: 2 errors in empty disjunction: - // nestedList.v2e.y.0.0: conflicting values int and [2] (mismatched types int and list): + // nestedList.v2e.y.0.0: conflicting values [2] and int (mismatched types list and int): // ./in.cue:443:12 // ./in.cue:444:11 - // nestedList.v2e.y.0.0: incompatible list lengths (1 and 2) - 0: (#list){ - 0: (int){ 2 } - } + // nestedList.v2e.y.0.0: incompatible list lengths (1 and 2): + // ./in.cue:444:6 + 0: (list){ list } 1: (int){ 1 } } 1: (int){ 1 } @@ -999,7 +1045,10 @@ head: (int){ 3 } tail: (struct){ head: (int){ 4 } - tail: (null){ null } + tail: ((null|struct)){ |((struct){ + head: (int){ int } + tail: (null){ null } + }, (null){ null }) } } } } @@ -1013,7 +1062,10 @@ head: (int){ 2 } tail: (struct){ head: (int){ 3 } - tail: (int){ 1 } + tail: ((int|struct)){ |((struct){ + head: (int){ int } + tail: (int){ 1 } + }, (int){ 1 }) } } } } @@ -1027,8 +1079,12 @@ head: (int){ 2 } tail: (struct){ |((struct){ head: (int){ 3 } - tail: (struct){ - } + tail: (struct){ |((struct){ + head: (int){ int } + tail: (struct){ + } + }, (struct){ + }) } }, (struct){ head: (int){ 3 } }) } @@ -1050,9 +1106,7 @@ // [structural cycle] f: (_|_){ // [structural cycle] - h: (_|_){ - // [structural cycle] z1.z.f.h: structural cycle - } + h: ~(z1.z.g) } g: (_|_){ // [structural cycle] @@ -1073,10 +1127,7 @@ x: (_){ _ } y: (_){ _ } } - y: (struct){ - x: (_){ _ } - y: (_){ _ } - } + y: ~(crossRefNoCycle.t1.C.x) } } t2: (struct){ @@ -1089,10 +1140,7 @@ x: (_){ _ } y: (_){ _ } } - y: (struct){ - x: (_){ _ } - y: (_){ _ } - } + y: ~(crossRefNoCycle.t2.C.x) } } t3: (struct){ @@ -1107,16 +1155,8 @@ y: (_){ _ } z: (_){ _ } } - y: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - z: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } + y: ~(crossRefNoCycle.t3.C.x) + z: ~(crossRefNoCycle.t3.C.x) } } t4: (struct){ @@ -1132,51 +1172,11 @@ y: (_){ _ } z: (_){ _ } } - y: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - z: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - } - y: (struct){ - x: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - y: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - z: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - } - z: (struct){ - x: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - y: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - z: (struct){ - x: (_){ _ } - y: (_){ _ } - z: (_){ _ } - } - } + y: ~(crossRefNoCycle.t4.C.x.x) + z: ~(crossRefNoCycle.t4.C.x.x) + } + y: ~(crossRefNoCycle.t4.C.x) + z: ~(crossRefNoCycle.t4.C.x) } } t5: (struct){ @@ -1187,18 +1187,8 @@ } } C: (struct){ - y: (struct){ - y: (_|_){ - // [incomplete] crossRefNoCycle.t5.C.y.y: undefined field: x: - // ./in.cue:556:8 - } - } - x: (struct){ - y: (_|_){ - // [incomplete] crossRefNoCycle.t5.C.x.y: undefined field: x: - // ./in.cue:556:8 - } - } + x: ~(crossRefNoCycle.t5.T) + y: ~(crossRefNoCycle.t5.T) } } } @@ -1221,19 +1211,19 @@ } } n4: (struct){ - a: (struct){ - b: (int){ int } - } - x: (struct){ - a: (struct){ - b: (int){ int } - } - y: (struct){ + x: (struct){ + y: (struct){ + z: (int){ int } a: (struct){ b: (int){ int } } - z: (int){ int } - } + } + a: (struct){ + b: (int){ int } + } + } + a: (struct){ + b: (int){ int } } } } -- diff/todo/p2 -- Investigate differing counts for empty disjunction errors. fieldsSumInfinite.issue3310.3: path missing in error b7.b.0.0.0: cycle too deep before detection. TODO(share): fix the following bug once we have structure sharing. p3.a.a: field not allowed incorrect? -- diff/todo/p3 -- n4: Reordering. b12b: reported at correct level, but investigate if it is not processing too deep anyway. -- diff/explanation -- Structural cycles are reported in all chains. compared to old implementation. b4.b: Structural error converted to eval error: there is both a structural and eval error at this field. The newly reported error is correct. b7.b.0.0: structural cycle nested one too deep: the eval error takes precedence. The cycle is reported at the correct level according to the spec. b10.c.d: position now allows b: string as well. This is correct. This is mostly a representational issue, as the evaluator would still accept such values when merged, but it is still useful. fieldsSumInfinite.issue3310: evalv3 correctly spots a structural cycle, where evalv2 computes an incorrect result without erroring. issue2545: a regression in evalv2 around v0.6 is fixed in evalv3. -- out/eval -- Errors: a1.f.0: structural cycle a3.f.g: structural cycle b12b.#list.tail: structural cycle b13.root.a.0.0: structural cycle b14.root.b.1.1: structural cycle b4.cond1.x.y.0: structural cycle b4.cond2.x.y.0: structural cycle b4.x.y.0: structural cycle b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): ./in.cue:94:5 ./in.cue:94:13 ./in.cue:94:14 ./in.cue:95:9 b6.b.a.0.0: structural cycle b6.x.a.0: structural cycle b7.a.0: structural cycle c1.a.c.c: structural cycle d1.a.b.c.d.t: structural cycle d2.a.b.c.d.t: structural cycle d2.r.c.d.t: structural cycle d3.x.a.b.c: structural cycle e1.a.c: structural cycle e1.b.c: structural cycle e2.a.c: structural cycle e2.b.c: structural cycle e3.a: conflicting values [a] and {c:a} (mismatched types list and struct): ./in.cue:412:5 ./in.cue:413:5 e3.a.c: structural cycle e3.b: conflicting values [b] and {c:b} (mismatched types list and struct): ./in.cue:415:5 ./in.cue:416:5 e3.b.c: structural cycle e4.a.0: 4 errors in empty disjunction: e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:420:10 ./in.cue:421:6 e4.a.0.0: 2 errors in empty disjunction: e4.a.0.0: conflicting values [[{c:1}]] and {c:1} (mismatched types list and struct): ./in.cue:421:5 ./in.cue:421:7 e4.a.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:420:6 ./in.cue:420:10 ./in.cue:421:6 e4.b.0: 4 errors in empty disjunction: e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:424:10 e4.b.0.0: 2 errors in empty disjunction: e4.b.0.0: conflicting values [(b|{})] and {c:1} (mismatched types list and struct): ./in.cue:423:7 ./in.cue:424:5 e4.b.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): ./in.cue:423:6 ./in.cue:424:6 ./in.cue:424:10 issue2545.#B.A: structural cycle nestedList.v1e.y.0: 4 errors in empty disjunction: nestedList.v1e.y.0: conflicting values int and [[2],1] (mismatched types int and list): ./in.cue:438:11 ./in.cue:439:11 nestedList.v1e.y.0.0: 2 errors in empty disjunction: nestedList.v1e.y.0.0: conflicting values int and [2] (mismatched types int and list): ./in.cue:438:11 ./in.cue:439:12 nestedList.v1e.y.0.0: incompatible list lengths (1 and 2) nestedList.v2e.y.0: 4 errors in empty disjunction: nestedList.v2e.y.0: conflicting values int and [[2],1] (mismatched types int and list): ./in.cue:443:11 ./in.cue:444:11 nestedList.v2e.y.0.0: 2 errors in empty disjunction: nestedList.v2e.y.0.0: conflicting values int and [2] (mismatched types int and list): ./in.cue:443:12 ./in.cue:444:11 nestedList.v2e.y.0.0: incompatible list lengths (1 and 2) p2.#T.a.b.link: structural cycle p3.#U.#T.a.b.link: structural cycle p5.#T.a.0.link: structural cycle p6.#U.#T.a.0.link: structural cycle patternFail.issue2374.a.b: structural cycle shortPathFail.elipsis.t2.Foo.ref.ref: structural cycle withLetFail.schema.next: structural cycle z1.z.f.h: structural cycle z1.z.g.h: structural cycle d1.r: structural cycle: ./in.cue:301:26 d3.x.indirect: structural cycle: ./in.cue:316:12 Result: (_|_){ // [eval] a1: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] a1.f.0: structural cycle } } } a2: (struct){ f: (_){ _ } } a3: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] g: (_|_){ // [structural cycle] a3.f.g: structural cycle } } } a4: (struct){ a: (#list){ 0: (int){ int } } } a5: (struct){ a: (struct){ b: (int){ int } } } a6: (struct){ a: (_){ |((_){ _ }, (int){ int }) } } a7: (struct){ a: (string){ "foo" } b: (struct){ x: (struct){ x: (string){ "foo" } y: (int){ 3 } } y: (string){ "foo" } } c: (struct){ x: (string){ "foo" } y: (int){ 3 } } } b1: (struct){ b: (#list){ 0: (int){ 1 } } a: (#list){ 0: (int){ int } } } b2: (struct){ a: (#list){ 0: (int){ int } } b: (#list){ 0: (int){ 1 } } } b3: (struct){ x: (struct){ a: (#list){ 0: (int){ int } } } b: (struct){ a: (#list){ 0: (int){ 1 } } } } b4: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b4.x.y.0: structural cycle } } x: (_|_){ // [structural cycle] y: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b4.x.y.0: structural cycle } } } cond1: (_|_){ // [structural cycle] b: (#list){ _z: (bool){ false } 0: (int){ 1 } } x: (_|_){ // [structural cycle] y: (_|_){ // [structural cycle] _z: (bool){ |(*(bool){ true }, (bool){ bool }) } 0: (_|_){ // [structural cycle] b4.cond1.x.y.0: structural cycle } } } } cond2: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] y: (_|_){ // [structural cycle] _z: (bool){ |(*(bool){ true }, (bool){ bool }) } 0: (_|_){ // [structural cycle] b4.cond2.x.y.0: structural cycle } } } b: (_|_){ // [structural cycle] b4.cond2.x.y.0: structural cycle } } } b5: (struct){ b: (struct){ a: (#list){ 0: (int){ 1 } } } x: (struct){ y: (struct){ a: (#list){ 0: (int){ int } } } } } b6: (_|_){ // [eval] b: (_|_){ // [eval] a: (_|_){ // [eval] 0: (_|_){ // [eval] b6.b.a.0: conflicting values 1 and [1] (mismatched types int and list): // ./in.cue:94:5 // ./in.cue:94:13 // ./in.cue:94:14 // ./in.cue:95:9 0: (_|_){ // [structural cycle] b6.b.a.0.0: structural cycle } } } } x: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b6.x.a.0: structural cycle } } } } b7: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b7.a.0: structural cycle } } a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b7.a.0: structural cycle } } } b8: (struct){ x: (struct){ f: (string){ string } } a: (struct){ f: (string){ string } } b: (string){ string } } b9: (struct){ #a: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } #b: (#struct){ c: (#list){ 0: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 1: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 2: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } } } #ref: (#struct){ ref: (string){ string } } x: (#struct){ |((#struct){ c: (#list){ 0: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 1: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } 2: ((string|struct)){ |((string){ string }, (#struct){ ref: (string){ string } }) } } }, (#struct){ ref: (string){ string } }) } } b10: (struct){ a: (#struct){ b: ((string|struct)){ |((string){ string }, (#struct){ d: (string){ string } }) } } c: (#struct){ d: (string){ string } } d: (struct){ d: (struct){ b: (string){ string } } } } b11: (struct){ #list: (#struct){ tail: ((null|struct)){ |(*(null){ null }, (#struct){ tail: (null){ null } }) } } } b12: (struct){ #list: (#struct){ value: (int){ int } tail: (null){ null } sum: (int){ int } } list1: (#struct){ value: (int){ 1 } tail: (#struct){ value: (int){ 2 } tail: (#struct){ value: (int){ 3 } tail: (#struct){ value: (int){ 4 } tail: (null){ null } sum: (int){ 4 } } sum: (int){ 7 } } sum: (int){ 9 } } sum: (int){ 10 } } } b12b: (_|_){ // [structural cycle] #list: (_|_){ // [structural cycle] b12b.#list.tail: structural cycle } list1: (_|_){ // [structural cycle] b12b.#list.tail: structural cycle } } b13: (_|_){ // [structural cycle] root: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] b13.root.a.0.0: structural cycle } } } } } b14: (_|_){ // [structural cycle] root: (_|_){ // [structural cycle] a: (list){ } b: (_|_){ // [structural cycle] 0: (list){ } 1: (_|_){ // [structural cycle] 0: (list){ } 1: (_|_){ // [structural cycle] b14.root.b.1.1: structural cycle } } } } } b15: (struct){ root: (struct){ a: (struct){ } } } p1: (struct){ #T: (#struct){ a: (#struct){ } } a: (#struct){ a: (#struct){ one: (#struct){ link: (#struct){ a: (#struct){ two: (#struct){ link: (#struct){ a: (#struct){ } } } } } } } } } p2: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p2.#T.a.b.link: structural cycle } } } } a: (_|_){ // [structural cycle] a: (struct){ one: (struct){ link: (struct){ a: (struct){ two: (struct){ } } } } } } } p3: (_|_){ // [structural cycle] #S: (#struct){ #T: (#struct){ a: (#struct){ } } } #U: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p3.#U.#T.a.b.link: structural cycle } } } } } a: (_|_){ // [structural cycle] p3.#U.#T.a.b.link: structural cycle } } p4: (struct){ #T: (#struct){ a: (list){ } } a: (#struct){ a: (#list){ 0: (#struct){ link: (#struct){ a: (#list){ 0: (#struct){ link: (#struct){ a: (list){ } } } } } } } } } p5: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p5.#T.a.0.link: structural cycle } } } } a: (_|_){ // [structural cycle] a: (#list){ 0: (struct){ link: (struct){ a: (#list){ 0: (struct){ } } } } } } } p6: (_|_){ // [structural cycle] #S: (#struct){ #T: (#struct){ a: (list){ } } } #U: (_|_){ // [structural cycle] #T: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] 0: (_|_){ // [structural cycle] link: (_|_){ // [structural cycle] p6.#U.#T.a.0.link: structural cycle } } } } } a: (_|_){ // [structural cycle] p6.#U.#T.a.0.link: structural cycle } } c1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (struct){ } c: (_|_){ // [structural cycle] b: (struct){ } c: (_|_){ // [structural cycle] c1.a.c.c: structural cycle } } } } d1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] h: (int){ int } t: (_|_){ // [structural cycle] d1.a.b.c.d.t: structural cycle } } } } } r: (_|_){ // [structural cycle] d1.r: structural cycle: // ./in.cue:301:26 } x: (_|_){ // [structural cycle] d1.a.b.c.d.t: structural cycle } } d2: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] h: (int){ int } t: (_|_){ // [structural cycle] } } } r: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] h: (int){ int } t: (_|_){ // [structural cycle] d2.r.c.d.t: structural cycle } } } } a: (struct){ b: (struct){ c: (_|_){ // [structural cycle] d: (_|_){ // [structural cycle] h: (int){ int } t: (_|_){ // [structural cycle] d2.a.b.c.d.t: structural cycle } } } } } } d3: (_|_){ // [structural cycle] config: (struct){ a: (struct){ b: (struct){ c: (null){ null } } } indirect: (null){ null } i: (int){ |(*(int){ 1 }, (int){ int }) } } x: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] d3.x.a.b.c: structural cycle } } } indirect: (_|_){ // [structural cycle] d3.x.indirect: structural cycle: // ./in.cue:316:12 } i: (int){ 0 } } } shortPathFail: (_|_){ // [structural cycle] doubleRef: (struct){ a: (#struct){ Next: (null){ null } } #List: (#struct){ Next: (null){ null } } } elipsis: (_|_){ // [structural cycle] t1: (struct){ #Foo: (#struct){ ref: ((null|struct)){ |((null){ null }, (#struct){ ref: (null){ null } }) } } } t2: (_|_){ // [structural cycle] Foo: (_|_){ // [structural cycle] ref: (_|_){ // [structural cycle] ref: (_|_){ // [structural cycle] shortPathFail.elipsis.t2.Foo.ref.ref: structural cycle } } } } } comprehension: (struct){ #list: (#struct){ tail: ((null|struct)){ |(*(null){ null }, (#struct){ tail: (null){ null } }) } } } } patternFail: (_|_){ // [structural cycle] issue2374: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] r: (int){ 0 } b: (_|_){ // [structural cycle] patternFail.issue2374.a.b: structural cycle } } } } withLetFail: (_|_){ // [structural cycle] schema: (_|_){ // [structural cycle] next: (_|_){ // [structural cycle] withLetFail.schema.next: structural cycle } } let _schema_1#1 = (_|_){ // [structural cycle] withLetFail._schema_1: structural cycle: // ./in.cue:362:17 } } fieldsSumInfinite: (_|_){ // [structural cycle] issue3310: (_|_){ // [structural cycle] cheeseburger: (float){ 3.00 } fries: (float){ 2.00 } sprite: (float){ 1.00 } total: (_|_){ // [structural cycle] } } } listOptOK: (struct){ list: (struct){ head: (int){ int } tail?: (_|_){ // [structural cycle] listOptOK.list.tail: structural cycle } } a: (struct){ head: (int){ 3 } tail: (struct){ head: (int){ 2 } tail?: (_|_){ // [structural cycle] listOptOK.a.tail.tail: structural cycle } } } } issue2545: (_|_){ // [structural cycle] #A: (#struct){ B?: (_|_){ // [structural cycle] A: (_|_){ // [structural cycle] issue2545.#A.B.A: structural cycle } } } #B: (_|_){ // [structural cycle] A: (_|_){ // [structural cycle] issue2545.#B.A: structural cycle } } } e1: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e1.a.c: structural cycle } } b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e1.b.c: structural cycle } } } e2: (_|_){ // [structural cycle] a: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e2.a.c: structural cycle } } b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] e2.b.c: structural cycle } } } e3: (_|_){ // [eval] a: (_|_){ // [eval] e3.a: conflicting values [a] and {c:a} (mismatched types list and struct): // ./in.cue:412:5 // ./in.cue:413:5 c: (_|_){ // [structural cycle] e3.a.c: structural cycle } 0: (_|_){ // [structural cycle] e3.a.c: structural cycle } } b: (_|_){ // [eval] e3.b: conflicting values [b] and {c:b} (mismatched types list and struct): // ./in.cue:415:5 // ./in.cue:416:5 c: (_|_){ // [structural cycle] e3.b.c: structural cycle } 0: (_|_){ // [structural cycle] e3.b.c: structural cycle } } } e4: (_|_){ // [eval] a: (_|_){ // [eval] 0: (_|_){ // [eval] e4.a.0: 4 errors in empty disjunction: // e4.a.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:420:10 // ./in.cue:421:6 // e4.a.0.0: 2 errors in empty disjunction: // e4.a.0.0: conflicting values [[{c:1}]] and {c:1} (mismatched types list and struct): // ./in.cue:421:5 // ./in.cue:421:7 // e4.a.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:420:6 // ./in.cue:420:10 // ./in.cue:421:6 0: (struct){ c: (int){ 1 } } } } b: (_|_){ // [eval] 0: (_|_){ // [eval] e4.b.0: 4 errors in empty disjunction: // e4.b.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:424:10 // e4.b.0.0: 2 errors in empty disjunction: // e4.b.0.0: conflicting values [(b|{})] and {c:1} (mismatched types list and struct): // ./in.cue:423:7 // ./in.cue:424:5 // e4.b.0.0: conflicting values [{c:1}] and {} (mismatched types list and struct): // ./in.cue:423:6 // ./in.cue:424:6 // ./in.cue:424:10 0: (struct){ c: (int){ 1 } } } } } e5: (struct){ a: (struct){ c: (int){ int } } b: (struct){ c: (int){ int } } } nestedList: (_|_){ // [eval] v1e: (_|_){ // [eval] x: (#list){ 0: (int){ int } 1: (int){ 1 } } y: (_|_){ // [eval] 0: (_|_){ // [eval] nestedList.v1e.y.0: 4 errors in empty disjunction: // nestedList.v1e.y.0: conflicting values int and [[2],1] (mismatched types int and list): // ./in.cue:438:11 // ./in.cue:439:11 // nestedList.v1e.y.0.0: 2 errors in empty disjunction: // nestedList.v1e.y.0.0: conflicting values int and [2] (mismatched types int and list): // ./in.cue:438:11 // ./in.cue:439:12 // nestedList.v1e.y.0.0: incompatible list lengths (1 and 2) 0: (#list){ 0: (int){ 2 } } 1: (int){ 1 } } 1: (int){ 1 } } } v2e: (_|_){ // [eval] y: (_|_){ // [eval] 0: (_|_){ // [eval] nestedList.v2e.y.0: 4 errors in empty disjunction: // nestedList.v2e.y.0: conflicting values int and [[2],1] (mismatched types int and list): // ./in.cue:443:11 // ./in.cue:444:11 // nestedList.v2e.y.0.0: 2 errors in empty disjunction: // nestedList.v2e.y.0.0: conflicting values int and [2] (mismatched types int and list): // ./in.cue:443:12 // ./in.cue:444:11 // nestedList.v2e.y.0.0: incompatible list lengths (1 and 2) 0: (#list){ 0: (int){ 2 } } 1: (int){ 1 } } 1: (int){ 1 } } x: (#list){ 0: (int){ int } 1: (int){ 1 } } } v1: (struct){ x: (#list){ 0: (int){ int } 1: (int){ 1 } } y: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 2 } 1: (int){ 1 } } 1: (int){ 1 } } 1: (int){ 1 } } } v2: (struct){ y: (#list){ 0: (#list){ 0: (#list){ 0: (int){ 2 } 1: (int){ 1 } } 1: (int){ 1 } } 1: (int){ 1 } } x: (#list){ 0: (int){ int } 1: (int){ 1 } } } } v3: (struct){ list: (struct){ head: (int){ int } tail: (null){ null } } myList: (struct){ head: (int){ 2 } tail: (struct){ head: (int){ 3 } tail: (struct){ head: (int){ 4 } tail: (null){ null } } } } } v4: (struct){ list: (struct){ head: (int){ int } tail: (int){ 1 } } myList: (struct){ head: (int){ 2 } tail: (struct){ head: (int){ 3 } tail: (int){ 1 } } } } v5: (struct){ list: (struct){ head: (int){ int } tail: (struct){ } } myList: (struct){ head: (int){ 2 } tail: (struct){ |((struct){ head: (int){ 3 } tail: (struct){ } }, (struct){ head: (int){ 3 } }) } } } z1: (_|_){ // [structural cycle] y: (struct){ f: (struct){ h: (_){ _ } } g: (_){ _ } } x: (struct){ f: (_){ _ } g: (_){ _ } } z: (_|_){ // [structural cycle] f: (_|_){ // [structural cycle] h: (_|_){ // [structural cycle] z1.z.f.h: structural cycle } } g: (_|_){ // [structural cycle] h: (_|_){ // [structural cycle] z1.z.g.h: structural cycle } } } } crossRefNoCycle: (struct){ t1: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } } C: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } } y: (struct){ x: (_){ _ } y: (_){ _ } } } } t2: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } } C: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } } y: (struct){ x: (_){ _ } y: (_){ _ } } } } t3: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } C: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } y: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } z: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } } } t4: (struct){ T: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } C: (struct){ x: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } y: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } z: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } } y: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } y: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } z: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } } z: (struct){ x: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } y: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } z: (struct){ x: (_){ _ } y: (_){ _ } z: (_){ _ } } } } } t5: (struct){ T: (struct){ y: (_|_){ // [incomplete] crossRefNoCycle.t5.T.y: undefined field: x: // ./in.cue:556:8 } } C: (struct){ y: (struct){ y: (_|_){ // [incomplete] crossRefNoCycle.t5.C.y.y: undefined field: x: // ./in.cue:556:8 } } x: (struct){ y: (_|_){ // [incomplete] crossRefNoCycle.t5.C.x.y: undefined field: x: // ./in.cue:556:8 } } } } } n1: (struct){ a: (struct){ b: (int){ int } } } n2: (struct){ a: (struct){ b: (int){ int } a: (struct){ b: (int){ int } } } } n3: (struct){ a: (struct){ b: (int){ int } } } n4: (struct){ a: (struct){ b: (int){ int } } x: (struct){ a: (struct){ b: (int){ int } } y: (struct){ a: (struct){ b: (int){ int } } z: (int){ int } } } } } -- out/compile -- --- in.cue { a1: { f: [ 〈1;f〉, ] } a2: { f: 〈0;f〉 } a3: { f: { g: 〈1;f〉 } } a4: { a: [ (〈1;a〉|int), ] } a5: { a: { b: (〈1;a〉|int) } } a6: { a: (〈0;a〉|int) } a7: { a: 〈0;c〉.x b: { x: 〈1;c〉 y: "foo" } c: { x: 〈1;b〉.y y: 3 } } b1: { b: (〈0;a〉 & [ 1, ]) a: [ (〈1;a〉|int), ] } b2: { a: [ (〈1;a〉|int), ] b: (〈0;a〉 & [ 1, ]) } b3: { x: { a: [ (〈1;a〉|int), ] } b: (〈0;x〉 & { a: [ 1, ] }) } b4: { b: (〈0;x〉.y & [ 1, ]) x: { y: [ 〈1;y〉, ] } } b4: { cond1: { b: (〈0;x〉.y & { _z: false [ 1, ] }) x: { y: { _z: (*true|bool) if 〈0;_z〉 { [ 〈3;y〉, ] } } } } } b4: { cond2: { x: { y: { _z: (*true|bool) if 〈0;_z〉 { [ 〈3;y〉, ] } } } b: (〈0;x〉.y & { _z: false [ 1, ] }) } } b5: { b: (〈0;x〉.y & { a: [ 1, ] }) x: { y: { a: [ (〈1;a〉|int), ] } } } b6: { b: (〈0;x〉 & { a: [ 1, ] }) x: { a: [ 〈1;a〉, ] } } b7: { b: (〈0;a〉 & [ [ 1, ], ]) a: [ 〈1;a〉, ] } b8: { x: 〈0;a〉 a: { f: 〈1;b〉 } b: (〈0;a〉|string) } b9: { #a: (string|〈0;#b〉|〈0;#ref〉) #b: { c: [ 〈2;#a〉, 〈2;#a〉, 〈2;#a〉, ] } #ref: { ref: string } x: (〈0;#b〉|〈0;#ref〉) } b10: { a: close({ b: (string|〈1;a〉|〈1;c〉) }) c: close({ d: (string|〈1;a〉) }) d: { d: { b: string } } } b11: { #list: { tail: (〈1;#list〉|*null) if (〈0;tail〉 != null) {} } } b12: { #list: { value: int tail: (〈1;#list〉|*null) if (〈0;tail〉 != null) { sum: (〈1;value〉 + 〈1;tail〉.sum) } if (〈0;tail〉 == null) { sum: 〈1;value〉 } } list1: 〈0;#list〉 list1: { value: 1 tail: { value: 2 tail: { value: 3 tail: { value: 4 } } } } } b12b: { #list: { tail: 〈1;#list〉 if (〈0;tail〉 != null) { sum: 〈1;tail〉.sum } } list1: 〈0;#list〉 list1: { tail: { tail: {} } } } b13: { root: { a: [ for _, x in 〈2;root〉 { 〈1;x〉 }, ] } } b14: { root: { a: [ ...int, ] for _, x in 〈0;a〉 { "\(〈1;x〉)": {} } b: [ for _, x in 〈2;root〉 { 〈1;x〉 }, ] } } b15: { root: { a: { for _, x in 〈2;root〉 { 〈1;x〉 } } } } p1: { #T: { a: { [string]: { link: 〈3;#T〉 } } } a: (〈0;#T〉 & { a: { one: { link: { a: { two: {} } } } } }) } p2: { #T: { a: { [string]: { link: 〈3;#T〉 } } a: { b: {} } } a: (〈0;#T〉 & { a: { one: { link: { a: { two: {} } } } } }) } p3: { #S: { #T: { a: { [string]: { link: 〈3;#T〉 } } } } #U: { 〈1;#S〉 #T: { a: { b: {} } } } a: (〈0;#U〉.#T & { a: { one: { link: { a: { two: {} } } } } }) } p4: { #T: { a: [ ...{ link: 〈3;#T〉 }, ] } a: (〈0;#T〉 & { a: [ { link: { a: [ {}, ] } }, ] }) } p5: { #T: { a: [ ...{ link: 〈3;#T〉 }, ] a: [ {}, ] } a: (〈0;#T〉 & { a: [ { link: { a: [ {}, ] } }, ] }) } p6: { #S: { #T: { a: [ ...{ link: 〈3;#T〉 }, ] } } #U: { 〈1;#S〉 #T: { a: [ {}, ] } } a: (〈0;#U〉.#T & { a: [ { link: { a: [ {}, ] } }, ] }) } c1: { a: { b: {} c: (〈1;a〉 & 〈0;b〉) } } d1: { a: { b: { c: { d: { h: int t: 〈4;r〉 } } } } r: 〈0;a〉.b x: 〈0;a〉.b.c } d2: { x: 〈0;a〉.b.c r: 〈0;a〉.b a: { b: { c: { d: { h: int t: 〈4;r〉 } } } } } d3: { config: { a: { b: { c: 〈2;indirect〉 } } indirect: [ 〈1;a〉.b, null, ][〈0;i〉] i: (int|*1) } x: (〈0;config〉 & { i: 0 }) } shortPathFail: _ shortPathFail: { doubleRef: { a: 〈0;#List〉 #List: { Next: (〈1;#List〉|*null) } } } shortPathFail: { elipsis: { t1: { #Foo: { ref: (null|〈1;#Foo〉) } #Foo: { ... } } t2: { Foo: { ref: 〈1;Foo〉 } Foo: { ... } } } } patternFail: { issue2374: { [string]: { b: 〈1;(〈0;-〉)〉 } a: { r: 0 } } } shortPathFail: { comprehension: { #list: { tail: (〈1;#list〉|*null) if (〈0;tail〉 != null) {} } } } withLetFail: { schema: { next: 〈1;let _schema_1#1〉 } let _schema_1#1 = 〈0;schema〉 } fieldsSumInfinite: { issue3310: { cheeseburger: 3.00 fries: 2.00 sprite: 1.00 total: 〈import;list〉.Sum([ for _, v in 〈2;issue3310〉 { 〈1;v〉 }, ]) } } listOptOK: { list: { head: int tail?: 〈1;list〉 } a: (〈0;list〉 & { head: 3 tail: { head: 2 } }) } issue2545: { #A: { B?: 〈1;#B〉 } #B: { A: 〈1;#A〉 } } e1: { a: 〈0;a〉 a: { c: 〈1;a〉 } b: { c: 〈1;b〉 } b: 〈0;b〉 } e2: { a: { 〈1;a〉 } a: { c: 〈1;a〉 } b: { c: 〈1;b〉 } b: { 〈1;b〉 } } e3: { a: [ 〈1;a〉, ] a: { c: 〈1;a〉 } b: [ 〈1;b〉, ] b: { c: 〈1;b〉 } } e4: { a: [ (〈1;a〉|{}), ] a: [ [ { c: 1 }, ], ] b: [ [ { c: 1 }, ], ] b: [ (〈1;b〉|{}), ] } e5: { a: { c: (〈1;a〉|int) } a: (〈0;a〉|int) b: (〈0;b〉|int) b: { c: (〈1;b〉|int) } } nestedList: { v1e: { x: [ (〈1;x〉|int), 1, ] y: (〈0;x〉 & [ [ [ 2, ], 1, ], 1, ]) } v2e: { y: (〈0;x〉 & [ [ [ 2, ], 1, ], 1, ]) x: [ (〈1;x〉|int), 1, ] } v1: { x: [ (〈1;x〉|int), 1, ] y: (〈0;x〉 & [ [ [ 2, 1, ], 1, ], 1, ]) } v2: { y: (〈0;x〉 & [ [ [ 2, 1, ], 1, ], 1, ]) x: [ (〈1;x〉|int), 1, ] } } v3: { list: { head: int tail: (〈1;list〉|null) } myList: 〈0;list〉 myList: { head: 2 tail: { head: 3 tail: { head: 4 } } } } v4: { list: { head: int tail: (〈1;list〉|1) } myList: 〈0;list〉 myList: { head: 2 tail: { head: 3 } } } v5: { list: { head: int tail: (〈1;list〉|{}) } myList: 〈0;list〉 myList: { head: 2 tail: { head: 3 } } } z1: { y: { f: { h: 〈1;g〉 } g: _ } x: { f: _ g: 〈0;f〉 } z: (〈0;x〉 & 〈0;y〉) } crossRefNoCycle: { t1: { T: { x: _ y: 〈0;x〉 } C: ({ x: 〈1;T〉 } & 〈0;T〉) } } crossRefNoCycle: { t2: { T: { x: _ y: 〈0;x〉 } C: (〈0;T〉 & { x: 〈1;T〉 }) } } crossRefNoCycle: { t3: { T: { x: _ y: 〈0;x〉 z: 〈0;y〉 } C: (〈0;T〉 & { x: 〈1;T〉 }) } } crossRefNoCycle: { t4: { T: { x: _ y: 〈0;x〉 z: 〈0;y〉 } C: (〈0;T〉 & { x: (〈1;T〉 & { x: 〈2;T〉 }) }) } } crossRefNoCycle: { t5: { T: { y: 〈1〉.x } C: (〈0;T〉 & { x: 〈1;T〉 }) } } n1: { a: { b: int } } n2: (〈0;n1〉 & { a: 〈1;n1〉 }) n3: (〈0;n1〉 & { 〈1;n1〉 }) n4: (〈0;n1〉 & { x: (〈1;n1〉 & { y: (〈2;n1〉 & { z: int }) }) }) } cue-lang-cue-db9cc73/cue/testdata/cycle/with_defaults.txtar000066400000000000000000000025611474664451600241160ustar00rootroot00000000000000-- in.cue -- range1: { min: *1 | int range: >min range: 8 } range2: { min: *1 | int max: int & >min } rg: range2 & { // min: 1 max: 8 } -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 11 Allocs: 5 Retain: 0 Unifications: 10 Conjuncts: 22 Disjuncts: 16 -- out/evalalpha -- (struct){ range1: (struct){ min: (int){ |(*(int){ 1 }, (int){ int }) } range: (int){ 8 } } range2: (struct){ min: (int){ |(*(int){ 1 }, (int){ int }) } max: (int){ &(>1, int) } } rg: (struct){ max: (int){ 8 } min: (int){ |(*(int){ 1 }, (int){ int }) } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -8,7 +8,7 @@ max: (int){ &(>1, int) } } rg: (struct){ - min: (int){ |(*(int){ 1 }, (int){ int }) } max: (int){ 8 } + min: (int){ |(*(int){ 1 }, (int){ int }) } } } -- diff/todo/p3 -- Reordering. -- out/eval -- (struct){ range1: (struct){ min: (int){ |(*(int){ 1 }, (int){ int }) } range: (int){ 8 } } range2: (struct){ min: (int){ |(*(int){ 1 }, (int){ int }) } max: (int){ &(>1, int) } } rg: (struct){ min: (int){ |(*(int){ 1 }, (int){ int }) } max: (int){ 8 } } } -- out/compile -- --- in.cue { range1: { min: (*1|int) range: >〈0;min〉 range: 8 } range2: { min: (*1|int) max: (int & >〈0;min〉) } rg: (〈0;range2〉 & { max: 8 }) } cue-lang-cue-db9cc73/cue/testdata/definitions/000077500000000000000000000000001474664451600214005ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/definitions/026_combined_definitions.txtar000066400000000000000000000114471474664451600272350ustar00rootroot00000000000000#name: combined definitions #evalPartial -- in.cue -- // Allow combining of structs within a definition #D1: { env: a: "A" env: b: "B" #def: {a: "A"} #def: {b: "B"} } d1: #D1 & {env: c: "C"} #D2: { a: int } #D2: { b: int } #D3: { env: a: "A" } #D3: { env: b: "B" } #D4: { env: #DC env: b: int } #DC: {a: int} -- out/def -- // Allow combining of structs within a definition #D1: { env: { a: "A" b: "B" } #def: { a: "A" b: "B" } } d1: #D1 & { env: { c: "C" } } #D2: { a: int b: int } #D3: { env: { a: "A" b: "B" } } #D4: { env: _|_ // field "b" not allowed in closed struct } #DC: { a: int } -- out/legacy-debug -- <0>{#D1: <1>C{env: <2>C{a: "A", b: "B"}, #def: <3>C{a: "A", b: "B"}}, d1: <4>C{env: _|_("C":field "c" not allowed in closed struct), #def: <5>C{a: "A", b: "B"}}, #D2: <6>C{a: int, b: int}, #D3: <7>C{env: <8>C{a: "A", b: "B"}}, #D4: <9>C{env: _|_(int:field "b" not allowed in closed struct)}, #DC: <10>C{a: int}} -- out/compile -- --- in.cue { #D1: { env: { a: "A" } env: { b: "B" } #def: { a: "A" } #def: { b: "B" } } d1: (〈0;#D1〉 & { env: { c: "C" } }) #D2: { a: int } #D2: { b: int } #D3: { env: { a: "A" } } #D3: { env: { b: "B" } } #D4: { env: 〈1;#DC〉 env: { b: int } } #DC: { a: int } } -- out/eval/stats -- Leaks: 0 Freed: 29 Reused: 24 Allocs: 5 Retain: 1 Unifications: 29 Conjuncts: 41 Disjuncts: 30 -- out/evalalpha -- Errors: #D4.env.b: field not allowed: ./in.cue:27:7 d1.env.c: field not allowed: ./in.cue:9:17 Result: (_|_){ // [eval] #D1: (#struct){ env: (#struct){ a: (string){ "A" } b: (string){ "B" } } #def: (#struct){ a: (string){ "A" } b: (string){ "B" } } } d1: (_|_){ // [eval] env: (_|_){ // [eval] c: (_|_){ // [eval] d1.env.c: field not allowed: // ./in.cue:9:17 } a: (string){ "A" } b: (string){ "B" } } #def: (#struct){ a: (string){ "A" } b: (string){ "B" } } } #D2: (#struct){ a: (int){ int } b: (int){ int } } #D3: (#struct){ env: (#struct){ a: (string){ "A" } b: (string){ "B" } } } #D4: (_|_){ // [eval] env: (_|_){ // [eval] b: (_|_){ // [eval] #D4.env.b: field not allowed: // ./in.cue:27:7 } a: (int){ int } } } #DC: (#struct){ a: (int){ int } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,12 +1,7 @@ Errors: #D4.env.b: field not allowed: - ./in.cue:26:7 ./in.cue:27:7 - ./in.cue:30:6 d1.env.c: field not allowed: - ./in.cue:3:7 - ./in.cue:4:7 - ./in.cue:9:5 ./in.cue:9:17 Result: @@ -26,15 +21,12 @@ // [eval] env: (_|_){ // [eval] - a: (string){ "A" } - b: (string){ "B" } c: (_|_){ // [eval] d1.env.c: field not allowed: - // ./in.cue:3:7 - // ./in.cue:4:7 - // ./in.cue:9:5 // ./in.cue:9:17 } + a: (string){ "A" } + b: (string){ "B" } } #def: (#struct){ a: (string){ "A" } @@ -55,13 +47,11 @@ // [eval] env: (_|_){ // [eval] - a: (int){ int } b: (_|_){ // [eval] #D4.env.b: field not allowed: - // ./in.cue:26:7 // ./in.cue:27:7 - // ./in.cue:30:6 - } + } + a: (int){ int } } } #DC: (#struct){ -- diff/todo/p2 -- Missing positions -- diff/todo/p3 -- Reordering -- out/eval -- Errors: #D4.env.b: field not allowed: ./in.cue:26:7 ./in.cue:27:7 ./in.cue:30:6 d1.env.c: field not allowed: ./in.cue:3:7 ./in.cue:4:7 ./in.cue:9:5 ./in.cue:9:17 Result: (_|_){ // [eval] #D1: (#struct){ env: (#struct){ a: (string){ "A" } b: (string){ "B" } } #def: (#struct){ a: (string){ "A" } b: (string){ "B" } } } d1: (_|_){ // [eval] env: (_|_){ // [eval] a: (string){ "A" } b: (string){ "B" } c: (_|_){ // [eval] d1.env.c: field not allowed: // ./in.cue:3:7 // ./in.cue:4:7 // ./in.cue:9:5 // ./in.cue:9:17 } } #def: (#struct){ a: (string){ "A" } b: (string){ "B" } } } #D2: (#struct){ a: (int){ int } b: (int){ int } } #D3: (#struct){ env: (#struct){ a: (string){ "A" } b: (string){ "B" } } } #D4: (_|_){ // [eval] env: (_|_){ // [eval] a: (int){ int } b: (_|_){ // [eval] #D4.env.b: field not allowed: // ./in.cue:26:7 // ./in.cue:27:7 // ./in.cue:30:6 } } } #DC: (#struct){ a: (int){ int } } } cue-lang-cue-db9cc73/cue/testdata/definitions/028_recursive_closing_starting_at_non-definition.txtar000066400000000000000000000036631474664451600342110ustar00rootroot00000000000000#name: recursive closing starting at non-definition #evalPartial -- in.cue -- z: a: { #B: { c: d: 1 c: f: 1 } } A: z & {a: {#B: {c: e: 2}}} -- out/def -- z: { a: { #B: { c: { d: 1 f: 1 } } } } A: z & { a: { #B: { c: { e: 2 } } } } -- out/export -- z: { a: {} } A: { a: {} } -- out/yaml -- z: a: {} A: a: {} -- out/json -- {"z":{"a":{}},"A":{"a":{}}} -- out/legacy-debug -- <0>{z: <1>{a: <2>{#B: <3>C{c: <4>C{d: 1, f: 1}}}}, A: <5>{a: <6>{#B: <7>C{c: _|_(2:field "e" not allowed in closed struct)}}}} -- out/compile -- --- in.cue { z: { a: { #B: { c: { d: 1 } c: { f: 1 } } } } A: (〈0;z〉 & { a: { #B: { c: { e: 2 } } } }) } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 8 Allocs: 6 Retain: 0 Unifications: 14 Conjuncts: 21 Disjuncts: 14 -- out/evalalpha -- (struct){ z: (struct){ a: (struct){ #B: (#struct){ c: (#struct){ d: (int){ 1 } f: (int){ 1 } } } } } A: (struct){ a: (struct){ #B: (#struct){ c: (#struct){ e: (int){ 2 } d: (int){ 1 } f: (int){ 1 } } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -13,9 +13,9 @@ a: (struct){ #B: (#struct){ c: (#struct){ - d: (int){ 1 } - f: (int){ 1 } e: (int){ 2 } + d: (int){ 1 } + f: (int){ 1 } } } } -- diff/explanation -- reordering -- out/eval -- (struct){ z: (struct){ a: (struct){ #B: (#struct){ c: (#struct){ d: (int){ 1 } f: (int){ 1 } } } } } A: (struct){ a: (struct){ #B: (#struct){ c: (#struct){ d: (int){ 1 } f: (int){ 1 } e: (int){ 2 } } } } } } cue-lang-cue-db9cc73/cue/testdata/definitions/032_definitions_with_embedding.txtar000066400000000000000000000067331474664451600304250ustar00rootroot00000000000000#name: definitions with embedding #evalPartial -- in.cue -- #E: { a: {b: int} } #S: { #E a: {c: int} b: 3 } // adding a field to a nested struct that is closed. #e1: #S & {a: d: 4} // literal struct not closed until after unification. #v1: #S & {a: c: 4} -- out/def -- #E: { a: { b: int } } #S: { a: { c: int } b: 3 #E } // adding a field to a nested struct that is closed. #e1: #S & { a: { d: 4 } } // literal struct not closed until after unification. #v1: #S & { a: { c: 4 } } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/legacy-debug -- <0>{#E: <1>C{a: <2>C{b: int}}, #S: <3>C{a: <4>C{b: int, c: int}, b: 3}, #e1: <5>C{a: _|_(4:field "d" not allowed in closed struct), b: 3}, #v1: <6>C{a: <7>C{b: int, c: 4}, b: 3}} -- out/compile -- --- in.cue { #E: { a: { b: int } } #S: { 〈1;#E〉 a: { c: int } b: 3 } #e1: (〈0;#S〉 & { a: { d: 4 } }) #v1: (〈0;#S〉 & { a: { c: 4 } }) } -- out/eval/stats -- Leaks: 0 Freed: 20 Reused: 16 Allocs: 4 Retain: 0 Unifications: 20 Conjuncts: 36 Disjuncts: 20 -- out/evalalpha -- Errors: #e1.a.d: field not allowed: ./in.cue:12:15 Result: (_|_){ // [eval] #E: (#struct){ a: (#struct){ b: (int){ int } } } #S: (#struct){ a: (#struct){ c: (int){ int } b: (int){ int } } b: (int){ 3 } } #e1: (_|_){ // [eval] a: (_|_){ // [eval] d: (_|_){ // [eval] #e1.a.d: field not allowed: // ./in.cue:12:15 } c: (int){ int } b: (int){ int } } b: (int){ 3 } } #v1: (#struct){ a: (#struct){ c: (int){ 4 } b: (int){ int } } b: (int){ 3 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,5 @@ Errors: #e1.a.d: field not allowed: - ./in.cue:2:5 - ./in.cue:6:2 - ./in.cue:7:5 - ./in.cue:12:6 ./in.cue:12:15 Result: @@ -16,8 +12,8 @@ } #S: (#struct){ a: (#struct){ - b: (int){ int } - c: (int){ int } + c: (int){ int } + b: (int){ int } } b: (int){ 3 } } @@ -25,23 +21,19 @@ // [eval] a: (_|_){ // [eval] - b: (int){ int } - c: (int){ int } d: (_|_){ // [eval] #e1.a.d: field not allowed: - // ./in.cue:2:5 - // ./in.cue:6:2 - // ./in.cue:7:5 - // ./in.cue:12:6 // ./in.cue:12:15 } + c: (int){ int } + b: (int){ int } } b: (int){ 3 } } #v1: (#struct){ a: (#struct){ - b: (int){ int } c: (int){ 4 } + b: (int){ int } } b: (int){ 3 } } -- diff/todo/p2 -- Reordering / missing positions. -- out/eval -- Errors: #e1.a.d: field not allowed: ./in.cue:2:5 ./in.cue:6:2 ./in.cue:7:5 ./in.cue:12:6 ./in.cue:12:15 Result: (_|_){ // [eval] #E: (#struct){ a: (#struct){ b: (int){ int } } } #S: (#struct){ a: (#struct){ b: (int){ int } c: (int){ int } } b: (int){ 3 } } #e1: (_|_){ // [eval] a: (_|_){ // [eval] b: (int){ int } c: (int){ int } d: (_|_){ // [eval] #e1.a.d: field not allowed: // ./in.cue:2:5 // ./in.cue:6:2 // ./in.cue:7:5 // ./in.cue:12:6 // ./in.cue:12:15 } } b: (int){ 3 } } #v1: (#struct){ a: (#struct){ b: (int){ int } c: (int){ 4 } } b: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/definitions/033_Issue_#153.txtar000066400000000000000000000057011474664451600245770ustar00rootroot00000000000000#name: Issue #153 #evalFull -- in.cue -- Foo: { listOfCloseds: [...#Closed] } #Closed: { a: int | *0 } Junk: { b: 2 } Foo & { listOfCloseds: [{ for k, v in Junk { "\(k)": v } }] } -- out/def -- Foo: { listOfCloseds: [...#Closed] } listOfCloseds: [_|_, // field "b" not allowed in closed struct ] #Closed: { a: int | *0 } Junk: { b: 2 } -- out/legacy-debug -- <0>{<1>{listOfCloseds: [_|_(<2>.v:field "b" not allowed in closed struct)]}, Foo: <3>{listOfCloseds: []}, #Closed: <4>C{a: 0}, Junk: <5>{b: 2}} -- out/compile -- --- in.cue { Foo: { listOfCloseds: [ ...〈2;#Closed〉, ] } #Closed: { a: (int|*0) } Junk: { b: 2 } (〈0;Foo〉 & { listOfCloseds: [ { for k, v in 〈3;Junk〉 { "\(〈1;k〉)": 〈1;v〉 } }, ] }) } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 9 Allocs: 6 Retain: 1 Unifications: 11 Conjuncts: 23 Disjuncts: 16 -- out/evalalpha -- Errors: listOfCloseds.0.b: field not allowed: ./in.cue:16:12 Result: (_|_){ // [eval] Foo: (struct){ listOfCloseds: (list){ } } #Closed: (#struct){ a: (int){ |(*(int){ 0 }, (int){ int }) } } Junk: (struct){ b: (int){ 2 } } listOfCloseds: (_|_){ // [eval] 0: (_|_){ // [eval] a: (int){ |(*(int){ 0 }, (int){ int }) } b: (_|_){ // [eval] listOfCloseds.0.b: field not allowed: // ./in.cue:16:12 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,12 +1,6 @@ Errors: listOfCloseds.0.b: field not allowed: - ./in.cue:2:18 - ./in.cue:2:21 - ./in.cue:5:10 - ./in.cue:13:1 - ./in.cue:14:18 - ./in.cue:15:3 - ./in.cue:16:4 + ./in.cue:16:12 Result: (_|_){ @@ -28,13 +22,7 @@ a: (int){ |(*(int){ 0 }, (int){ int }) } b: (_|_){ // [eval] listOfCloseds.0.b: field not allowed: - // ./in.cue:2:18 - // ./in.cue:2:21 - // ./in.cue:5:10 - // ./in.cue:13:1 - // ./in.cue:14:18 - // ./in.cue:15:3 - // ./in.cue:16:4 + // ./in.cue:16:12 } } } -- diff/todo/p3 -- missing error positions -- out/eval -- Errors: listOfCloseds.0.b: field not allowed: ./in.cue:2:18 ./in.cue:2:21 ./in.cue:5:10 ./in.cue:13:1 ./in.cue:14:18 ./in.cue:15:3 ./in.cue:16:4 Result: (_|_){ // [eval] Foo: (struct){ listOfCloseds: (list){ } } #Closed: (#struct){ a: (int){ |(*(int){ 0 }, (int){ int }) } } Junk: (struct){ b: (int){ 2 } } listOfCloseds: (_|_){ // [eval] 0: (_|_){ // [eval] a: (int){ |(*(int){ 0 }, (int){ int }) } b: (_|_){ // [eval] listOfCloseds.0.b: field not allowed: // ./in.cue:2:18 // ./in.cue:2:21 // ./in.cue:5:10 // ./in.cue:13:1 // ./in.cue:14:18 // ./in.cue:15:3 // ./in.cue:16:4 } } } } cue-lang-cue-db9cc73/cue/testdata/definitions/036_closing_with_failed_optional.txtar000066400000000000000000000070061474664451600307610ustar00rootroot00000000000000#name: closing with failed optional #evalPartial -- in.cue -- #k1: {a: int, b?: int} & #A // closed({a: int}) #k2: #A & {a: int, b?: int} // closed({a: int}) o1: {a?: 3} & {a?: 4} // {a?: _|_} // Optional fields with error values can be elimintated when closing #o2: {a?: 3} & {a?: 4} // close({}) #d1: {a?: 2, b: 4} | {a?: 3, c: 5} v1: #d1 & {a?: 3, b: 4} // close({b: 4}) #A: {a: int} -- out/def -- #k1: { a: int b?: int } & #A #A: { a: int } #k2: #A & { a: int b?: int } o1: { a?: _|_ // conflicting values 3 and 4 } // Optional fields with error values can be elimintated when closing #o2: { a?: _|_ // conflicting values 3 and 4 } #d1: { a?: 2 b: 4 } | { a?: 3 c: 5 } v1: #d1 & { a?: 3 b: 4 } -- out/export -- o1: {} v1: { b: 4 } -- out/yaml -- o1: {} v1: b: 4 -- out/json -- {"o1":{},"v1":{"b":4}} -- out/legacy-debug -- <0>{#k1: <1>C{a: int}, #A: <2>C{a: int}, #k2: <3>C{a: int}, o1: <4>{a?: _|_((3 & 4):conflicting values 3 and 4)}, #o2: <5>C{a?: _|_((3 & 4):conflicting values 3 and 4)}, #d1: (<6>C{a?: 2, b: 4} | <7>C{a?: 3, c: 5}), v1: <8>C{a?: _|_((2 & 3):conflicting values 2 and 3), b: 4}} -- out/compile -- --- in.cue { #k1: ({ a: int b?: int } & 〈0;#A〉) #k2: (〈0;#A〉 & { a: int b?: int }) o1: ({ a?: 3 } & { a?: 4 }) #o2: ({ a?: 3 } & { a?: 4 }) #d1: ({ a?: 2 b: 4 }|{ a?: 3 c: 5 }) v1: (〈0;#d1〉 & { a?: 3 b: 4 }) #A: { a: int } } -- out/eval/stats -- Leaks: 0 Freed: 28 Reused: 23 Allocs: 5 Retain: 1 Unifications: 24 Conjuncts: 43 Disjuncts: 29 -- out/evalalpha -- (struct){ #k1: (#struct){ a: (int){ int } b?: (int){ int } } #k2: (#struct){ a: (int){ int } b?: (int){ int } } o1: (struct){ a?: (_|_){ // [eval] o1.a: conflicting values 4 and 3: // ./in.cue:5:10 // ./in.cue:5:20 } } #o2: (#struct){ a?: (_|_){ // [eval] #o2.a: conflicting values 4 and 3: // ./in.cue:8:11 // ./in.cue:8:21 } } #d1: (#struct){ |((#struct){ a?: (int){ 2 } b: (int){ 4 } }, (#struct){ a?: (int){ 3 } c: (int){ 5 } }) } v1: (#struct){ a?: (_|_){ // [eval] v1.a: conflicting values 2 and 3: // ./in.cue:10:11 // ./in.cue:12:16 } b: (int){ 4 } } #A: (#struct){ a: (int){ int } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -32,7 +32,6 @@ a?: (_|_){ // [eval] v1.a: conflicting values 2 and 3: // ./in.cue:10:11 - // ./in.cue:12:5 // ./in.cue:12:16 } b: (int){ 4 } -- diff/todo/p2 -- v1.a: Incorrect path in error message. -- diff/todo/p3 -- Missing error position. -- out/eval -- (struct){ #k1: (#struct){ a: (int){ int } b?: (int){ int } } #k2: (#struct){ a: (int){ int } b?: (int){ int } } o1: (struct){ a?: (_|_){ // [eval] o1.a: conflicting values 4 and 3: // ./in.cue:5:10 // ./in.cue:5:20 } } #o2: (#struct){ a?: (_|_){ // [eval] #o2.a: conflicting values 4 and 3: // ./in.cue:8:11 // ./in.cue:8:21 } } #d1: (#struct){ |((#struct){ a?: (int){ 2 } b: (int){ 4 } }, (#struct){ a?: (int){ 3 } c: (int){ 5 } }) } v1: (#struct){ a?: (_|_){ // [eval] v1.a: conflicting values 2 and 3: // ./in.cue:10:11 // ./in.cue:12:5 // ./in.cue:12:16 } b: (int){ 4 } } #A: (#struct){ a: (int){ int } } } cue-lang-cue-db9cc73/cue/testdata/definitions/036_optionals_in_open_structs.txtar000066400000000000000000000021141474664451600303600ustar00rootroot00000000000000#name: optionals in open structs #evalFull -- in.cue -- A: { [=~"^[a-s]*$"]: int } B: { [=~"^[m-z]*$"]: int } #C: {A & B} c: #C & {aaa: 3} -- out/def -- A: { [=~"^[a-s]*$"]: int } B: { [=~"^[m-z]*$"]: int } #C: { A & B } c: #C & { aaa: 3 } -- out/export -- A: {} B: {} c: { aaa: 3 } -- out/yaml -- A: {} B: {} c: aaa: 3 -- out/json -- {"A":{},"B":{},"c":{"aaa":3}} -- out/legacy-debug -- <0>{A: <1>{[=~"^[a-s]*$"]: <2>(_: string)->int, }, B: <3>{[=~"^[m-z]*$"]: <4>(_: string)->int, }, #C: <5>C{[=~"^[a-s]*$"]: <6>(_: string)->int, [=~"^[m-z]*$"]: <7>(_: string)->int, }, c: <8>C{[=~"^[a-s]*$"]: <9>(_: string)->int, [=~"^[m-z]*$"]: <10>(_: string)->int, aaa: 3}} -- out/compile -- --- in.cue { A: { [=~"^[a-s]*$"]: int } B: { [=~"^[m-z]*$"]: int } #C: { (〈1;A〉 & 〈1;B〉) } c: (〈0;#C〉 & { aaa: 3 }) } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 3 Allocs: 3 Retain: 0 Unifications: 6 Conjuncts: 17 Disjuncts: 6 -- out/eval -- (struct){ A: (struct){ } B: (struct){ } #C: (#struct){ } c: (#struct){ aaa: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/definitions/037_closing_with_comprehensions.txtar000066400000000000000000000077551474664451600307000ustar00rootroot00000000000000#name: closing with comprehensions #evalPartial -- in.cue -- #A: {f1: int, f2: int} for k, v in {f3: int} { a: #A & {"\(k)": v} } #B: { for k, v in {f1: int} { "\(k)": v } } #C: { f1: _ for k, v in {f1: int} { "\(k)": v } } #D: { for k, v in {f1: int} { "\(k)": v } ... } #E: #A & { for k, v in {f3: int} { "\(k)": v } } -- out/def -- #A: { f1: int f2: int } a: _|_ // field "f3" not allowed in closed struct #B: { f1: v } #C: { f1: { _ v ... } } #D: { f1: v ... } #E: _|_ // field "f3" not allowed in closed struct -- out/legacy-debug -- <0>{#A: <1>C{f1: int, f2: int}, a: _|_(<2>.v:field "f3" not allowed in closed struct), #B: <3>C{f1: int}, #C: <4>C{f1: int}, #D: <5>{f1: int, ...}, #E: _|_(<6>.v:field "f3" not allowed in closed struct)} -- out/compile -- --- in.cue { #A: { f1: int f2: int } for k, v in { f3: int } { a: (〈2;#A〉 & { "\(〈2;k〉)": 〈2;v〉 }) } #B: { for k, v in { f1: int } { "\(〈1;k〉)": 〈1;v〉 } } #C: { f1: _ for k, v in { f1: int } { "\(〈1;k〉)": 〈1;v〉 } } #D: { for k, v in { f1: int } { "\(〈1;k〉)": 〈1;v〉 } ... } #E: (〈0;#A〉 & { for k, v in { f3: int } { "\(〈1;k〉)": 〈1;v〉 } }) } -- out/eval/stats -- Leaks: 10 Freed: 18 Reused: 15 Allocs: 13 Retain: 10 Unifications: 28 Conjuncts: 43 Disjuncts: 28 -- out/evalalpha -- Errors: a.f3: field not allowed: ./in.cue:4:19 #E.f3: field not allowed: ./in.cue:29:11 Result: (_|_){ // [eval] #A: (#struct){ f1: (int){ int } f2: (int){ int } } a: (_|_){ // [eval] f1: (int){ int } f2: (int){ int } f3: (_|_){ // [eval] a.f3: field not allowed: // ./in.cue:4:19 } } #B: (#struct){ f1: (int){ int } } #C: (#struct){ f1: (int){ int } } #D: (#struct){ f1: (int){ int } } #E: (_|_){ // [eval] f1: (int){ int } f2: (int){ int } f3: (_|_){ // [eval] #E.f3: field not allowed: // ./in.cue:29:11 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,15 +1,8 @@ Errors: -#E.f3: field not allowed: - ./in.cue:1:5 - ./in.cue:27:5 - ./in.cue:27:10 - ./in.cue:28:2 - ./in.cue:29:3 a.f3: field not allowed: - ./in.cue:1:5 - ./in.cue:3:1 - ./in.cue:4:5 - ./in.cue:4:11 + ./in.cue:4:19 +#E.f3: field not allowed: + ./in.cue:29:11 Result: (_|_){ @@ -24,10 +17,7 @@ f2: (int){ int } f3: (_|_){ // [eval] a.f3: field not allowed: - // ./in.cue:1:5 - // ./in.cue:3:1 - // ./in.cue:4:5 - // ./in.cue:4:11 + // ./in.cue:4:19 } } #B: (#struct){ @@ -45,11 +35,7 @@ f2: (int){ int } f3: (_|_){ // [eval] #E.f3: field not allowed: - // ./in.cue:1:5 - // ./in.cue:27:5 - // ./in.cue:27:10 - // ./in.cue:28:2 - // ./in.cue:29:3 + // ./in.cue:29:11 } } } -- diff/todo/p2 -- error positions -- out/eval -- Errors: #E.f3: field not allowed: ./in.cue:1:5 ./in.cue:27:5 ./in.cue:27:10 ./in.cue:28:2 ./in.cue:29:3 a.f3: field not allowed: ./in.cue:1:5 ./in.cue:3:1 ./in.cue:4:5 ./in.cue:4:11 Result: (_|_){ // [eval] #A: (#struct){ f1: (int){ int } f2: (int){ int } } a: (_|_){ // [eval] f1: (int){ int } f2: (int){ int } f3: (_|_){ // [eval] a.f3: field not allowed: // ./in.cue:1:5 // ./in.cue:3:1 // ./in.cue:4:5 // ./in.cue:4:11 } } #B: (#struct){ f1: (int){ int } } #C: (#struct){ f1: (int){ int } } #D: (#struct){ f1: (int){ int } } #E: (_|_){ // [eval] f1: (int){ int } f2: (int){ int } f3: (_|_){ // [eval] #E.f3: field not allowed: // ./in.cue:1:5 // ./in.cue:27:5 // ./in.cue:27:10 // ./in.cue:28:2 // ./in.cue:29:3 } } } cue-lang-cue-db9cc73/cue/testdata/definitions/037_conjunction_of_optional_sets.txtar000066400000000000000000000076131474664451600310440ustar00rootroot00000000000000#name: conjunction of optional sets #evalFull -- in.cue -- #A: { [=~"^[a-s]*$"]: int } #B: { [=~"^[m-z]*$"]: int } #C: #A & #B c: #C & {aaa: 3} #D: {#A & #B} d: #D & {aaa: 3} -- out/def -- #A: { [=~"^[a-s]*$"]: int } #B: { [=~"^[m-z]*$"]: int } #C: #A & #B c: _|_ // field "aaa" not allowed in closed struct #D: { #A & #B } d: _|_ // field "aaa" not allowed in closed struct -- out/legacy-debug -- <0>{#A: <1>C{[=~"^[a-s]*$"]: <2>(_: string)->int, }, #B: <3>C{[=~"^[m-z]*$"]: <4>(_: string)->int, }, #C: <5>C{(C{[=~"^[a-s]*$"]: <6>(_: string)->int} & C{[=~"^[m-z]*$"]: <7>(_: string)->int}), }, c: _|_(3:field "aaa" not allowed in closed struct), #D: <8>C{(C{[=~"^[a-s]*$"]: <9>(_: string)->int} & C{[=~"^[m-z]*$"]: <10>(_: string)->int}), }, d: _|_(3:field "aaa" not allowed in closed struct)} -- out/compile -- --- in.cue { #A: { [=~"^[a-s]*$"]: int } #B: { [=~"^[m-z]*$"]: int } #C: (〈0;#A〉 & 〈0;#B〉) c: (〈0;#C〉 & { aaa: 3 }) #D: { (〈1;#A〉 & 〈1;#B〉) } d: (〈0;#D〉 & { aaa: 3 }) } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 6 Allocs: 3 Retain: 0 Unifications: 9 Conjuncts: 29 Disjuncts: 9 -- out/evalalpha -- Errors: c.aaa: field not allowed: ./in.cue:5:18 ./in.cue:2:2 ./in.cue:9:11 d.aaa: field not allowed: ./in.cue:5:18 ./in.cue:2:2 ./in.cue:12:10 Result: (_|_){ // [eval] #A: (#struct){ } #B: (#struct){ } #C: (#struct){ } c: (_|_){ // [eval] aaa: (_|_){ // [eval] c.aaa: field not allowed: // ./in.cue:5:18 // ./in.cue:2:2 // ./in.cue:9:11 } } #D: (#struct){ } d: (_|_){ // [eval] aaa: (_|_){ // [eval] d.aaa: field not allowed: // ./in.cue:5:18 // ./in.cue:2:2 // ./in.cue:12:10 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,18 +1,11 @@ Errors: c.aaa: field not allowed: - ./in.cue:2:2 - ./in.cue:4:5 - ./in.cue:8:5 - ./in.cue:8:10 - ./in.cue:9:5 + ./in.cue:5:18 + ./in.cue:2:2 ./in.cue:9:11 d.aaa: field not allowed: - ./in.cue:2:2 - ./in.cue:4:5 - ./in.cue:11:5 - ./in.cue:11:6 - ./in.cue:11:11 - ./in.cue:12:4 + ./in.cue:5:18 + ./in.cue:2:2 ./in.cue:12:10 Result: @@ -28,11 +21,8 @@ // [eval] aaa: (_|_){ // [eval] c.aaa: field not allowed: - // ./in.cue:2:2 - // ./in.cue:4:5 - // ./in.cue:8:5 - // ./in.cue:8:10 - // ./in.cue:9:5 + // ./in.cue:5:18 + // ./in.cue:2:2 // ./in.cue:9:11 } } @@ -42,12 +32,8 @@ // [eval] aaa: (_|_){ // [eval] d.aaa: field not allowed: - // ./in.cue:2:2 - // ./in.cue:4:5 - // ./in.cue:11:5 - // ./in.cue:11:6 - // ./in.cue:11:11 - // ./in.cue:12:4 + // ./in.cue:5:18 + // ./in.cue:2:2 // ./in.cue:12:10 } } -- diff/todo/p2 -- Missing positions. -- out/eval -- Errors: c.aaa: field not allowed: ./in.cue:2:2 ./in.cue:4:5 ./in.cue:8:5 ./in.cue:8:10 ./in.cue:9:5 ./in.cue:9:11 d.aaa: field not allowed: ./in.cue:2:2 ./in.cue:4:5 ./in.cue:11:5 ./in.cue:11:6 ./in.cue:11:11 ./in.cue:12:4 ./in.cue:12:10 Result: (_|_){ // [eval] #A: (#struct){ } #B: (#struct){ } #C: (#struct){ } c: (_|_){ // [eval] aaa: (_|_){ // [eval] c.aaa: field not allowed: // ./in.cue:2:2 // ./in.cue:4:5 // ./in.cue:8:5 // ./in.cue:8:10 // ./in.cue:9:5 // ./in.cue:9:11 } } #D: (#struct){ } d: (_|_){ // [eval] aaa: (_|_){ // [eval] d.aaa: field not allowed: // ./in.cue:2:2 // ./in.cue:4:5 // ./in.cue:11:5 // ./in.cue:11:6 // ./in.cue:11:11 // ./in.cue:12:4 // ./in.cue:12:10 } } } cue-lang-cue-db9cc73/cue/testdata/definitions/038_continue_recursive_closing_for_optionals.txtar000066400000000000000000000033411474664451600334460ustar00rootroot00000000000000#name: continue recursive closing for optionals #evalFull -- in.cue -- #S: { [string]: {a: int} } a: #S & { v: {b: int} } -- out/def -- #S: { [string]: { a: int } } a: #S & { v: { b: int } } -- out/legacy-debug -- <0>{#S: <1>{[]: <2>(_: string)-><3>C{a: int}, }, a: <4>{[]: <5>(_: string)-><6>C{a: int}, v: _|_(int:field "b" not allowed in closed struct)}} -- out/compile -- --- in.cue { #S: { [string]: { a: int } } a: (〈0;#S〉 & { v: { b: int } }) } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 2 Allocs: 4 Retain: 0 Unifications: 6 Conjuncts: 9 Disjuncts: 6 -- out/evalalpha -- Errors: a.v.b: field not allowed: ./in.cue:5:6 Result: (_|_){ // [eval] #S: (#struct){ } a: (_|_){ // [eval] v: (_|_){ // [eval] b: (_|_){ // [eval] a.v.b: field not allowed: // ./in.cue:5:6 } a: (int){ int } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,5 @@ Errors: a.v.b: field not allowed: - ./in.cue:2:12 - ./in.cue:4:4 ./in.cue:5:6 Result: @@ -15,8 +13,6 @@ // [eval] b: (_|_){ // [eval] a.v.b: field not allowed: - // ./in.cue:2:12 - // ./in.cue:4:4 // ./in.cue:5:6 } a: (int){ int } -- diff/todo/p2 -- Missing positions. -- out/eval -- Errors: a.v.b: field not allowed: ./in.cue:2:12 ./in.cue:4:4 ./in.cue:5:6 Result: (_|_){ // [eval] #S: (#struct){ } a: (_|_){ // [eval] v: (_|_){ // [eval] b: (_|_){ // [eval] a.v.b: field not allowed: // ./in.cue:2:12 // ./in.cue:4:4 // ./in.cue:5:6 } a: (int){ int } } } } cue-lang-cue-db9cc73/cue/testdata/definitions/039_augment_closed_optionals.txtar000066400000000000000000000032171474664451600301430ustar00rootroot00000000000000#name: augment closed optionals #evalFull -- in.cue -- #A: { [=~"^[a-s]*$"]: int } #B: { [=~"^[m-z]*?"]: int } #C: { #A & #B {[=~"^Q*$"]: int} } c: #C & {QQ: 3} #D: { #A #B } d: #D & {aaa: 4} -- out/def -- #A: { [=~"^[a-s]*$"]: int } #B: { [=~"^[m-z]*?"]: int } #C: { #A & #B {[=~"^Q*$"]: int} } c: #C & { QQ: 3 } #D: { #A #B } d: #D & { aaa: 4 } -- out/export -- c: { QQ: 3 } d: { aaa: 4 } -- out/yaml -- c: QQ: 3 d: aaa: 4 -- out/json -- {"c":{"QQ":3},"d":{"aaa":4}} -- out/legacy-debug -- <0>{#A: <1>C{[=~"^[a-s]*$"]: <2>(_: string)->int, }, #B: <3>C{[=~"^[m-z]*?"]: <4>(_: string)->int, }, #C: <5>C{C{[=~"^Q*$"]: <6>(_: string)->int}, C{(C{[=~"^[a-s]*$"]: <7>(_: string)->int} & C{[=~"^[m-z]*?"]: <8>(_: string)->int})}, }, c: <9>C{C{[=~"^Q*$"]: <10>(_: string)->int}, C{(C{[=~"^[a-s]*$"]: <11>(_: string)->int} & C{[=~"^[m-z]*?"]: <12>(_: string)->int})}, QQ: 3}, #D: <13>C{[=~"^[a-s]*$"]: <14>(_: string)->int, [=~"^[m-z]*?"]: <15>(_: string)->int, }, d: <16>C{[=~"^[a-s]*$"]: <17>(_: string)->int, [=~"^[m-z]*?"]: <18>(_: string)->int, aaa: 4}} -- out/compile -- --- in.cue { #A: { [=~"^[a-s]*$"]: int } #B: { [=~"^[m-z]*?"]: int } #C: { (〈1;#A〉 & 〈1;#B〉) { [=~"^Q*$"]: int } } c: (〈0;#C〉 & { QQ: 3 }) #D: { 〈1;#A〉 〈1;#B〉 } d: (〈0;#D〉 & { aaa: 4 }) } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 6 Allocs: 3 Retain: 0 Unifications: 9 Conjuncts: 35 Disjuncts: 9 -- out/eval -- (struct){ #A: (#struct){ } #B: (#struct){ } #C: (#struct){ } c: (#struct){ QQ: (int){ 3 } } #D: (#struct){ } d: (#struct){ aaa: (int){ 4 } } } cue-lang-cue-db9cc73/cue/testdata/definitions/comprehensions.txtar000066400000000000000000000014651474664451600255260ustar00rootroot00000000000000-- in.cue -- issue595: { // NOTE: this should eval with an EVAL error, not // an incomplete error. See Issue #595. #cfgs: [{ name: "foo" }] for cfg in #cfgs { files: cfg.nam } } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 1 Allocs: 5 Retain: 0 Unifications: 6 Conjuncts: 6 Disjuncts: 6 -- out/eval -- Errors: issue595.files: undefined field: nam: ./in.cue:8:14 Result: (_|_){ // [eval] issue595: (_|_){ // [eval] #cfgs: (#list){ 0: (#struct){ name: (string){ "foo" } } } files: (_|_){ // [eval] issue595.files: undefined field: nam: // ./in.cue:8:14 } } } -- out/compile -- --- in.cue { issue595: { #cfgs: [ { name: "foo" }, ] for _, cfg in 〈0;#cfgs〉 { files: 〈1;cfg〉.nam } } } cue-lang-cue-db9cc73/cue/testdata/definitions/defembed.txtar000066400000000000000000000027361474664451600242270ustar00rootroot00000000000000-- in.cue -- a: { #A } a: c: 1 #A: b: 1 -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 2 Allocs: 4 Retain: 1 Unifications: 6 Conjuncts: 9 Disjuncts: 7 -- out/evalalpha -- Errors: a.c: field not allowed: ./in.cue:5:4 Result: (_|_){ // [eval] a: (_|_){ // [eval] c: (_|_){ // [eval] a.c: field not allowed: // ./in.cue:5:4 } b: (int){ 1 } } #A: (#struct){ b: (int){ 1 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,6 @@ Errors: a.c: field not allowed: - ./in.cue:1:4 - ./in.cue:2:2 ./in.cue:5:4 - ./in.cue:7:5 Result: (_|_){ @@ -10,14 +7,11 @@ // [eval] a: (_|_){ // [eval] - b: (int){ 1 } c: (_|_){ // [eval] a.c: field not allowed: - // ./in.cue:1:4 - // ./in.cue:2:2 // ./in.cue:5:4 - // ./in.cue:7:5 } + b: (int){ 1 } } #A: (#struct){ b: (int){ 1 } -- diff/todo/p2 -- Missing positions / reordering. -- out/eval -- Errors: a.c: field not allowed: ./in.cue:1:4 ./in.cue:2:2 ./in.cue:5:4 ./in.cue:7:5 Result: (_|_){ // [eval] a: (_|_){ // [eval] b: (int){ 1 } c: (_|_){ // [eval] a.c: field not allowed: // ./in.cue:1:4 // ./in.cue:2:2 // ./in.cue:5:4 // ./in.cue:7:5 } } #A: (#struct){ b: (int){ 1 } } } -- out/compile -- --- in.cue { a: { 〈1;#A〉 } a: { c: 1 } #A: { b: 1 } } cue-lang-cue-db9cc73/cue/testdata/definitions/dynamic.txtar000066400000000000000000000020551474664451600241120ustar00rootroot00000000000000-- in.cue -- #A: { a: "foo" "\(a)": 3 } #B: a: b: { c: string d: 2 } #C: a: b: { c: *"d" | string (c): 2 } x: #B & #C -- out/eval/stats -- Leaks: 0 Freed: 23 Reused: 16 Allocs: 7 Retain: 1 Unifications: 19 Conjuncts: 29 Disjuncts: 23 -- out/eval -- (struct){ #A: (#struct){ a: (string){ "foo" } foo: (int){ 3 } } #B: (#struct){ a: (#struct){ b: (#struct){ c: (string){ string } d: (int){ 2 } } } } #C: (#struct){ a: (#struct){ b: (#struct){ c: (string){ |(*(string){ "d" }, (string){ string }) } d: (int){ 2 } } } } x: (#struct){ a: (#struct){ b: (#struct){ c: (string){ |(*(string){ "d" }, (string){ string }) } d: (int){ 2 } } } } } -- out/compile -- --- in.cue { #A: { a: "foo" "\(〈0;a〉)": 3 } #B: { a: { b: { c: string d: 2 } } } #C: { a: { b: { c: (*"d"|string) 〈0;c〉: 2 } } } x: (〈0;#B〉 & 〈0;#C〉) } cue-lang-cue-db9cc73/cue/testdata/definitions/embed.txtar000066400000000000000000000173461474664451600235530ustar00rootroot00000000000000-- in.cue -- deployment: [string]: #Deployment deployment: foo: spec: replicas: 1 #Deployment: { #TypeMeta spec: #Spec } #Spec: replicas: int #TypeMeta: {} recloseSimple: { #foo: {} a: {#foo} & {b: int} } // Reclosing reclose1: { #D: { x: int y: int } #a: { #D b: { c: int } } z: #a.b z: d: 3 // don't allow this } reclose2: { #D: { x: int y: int } a: { #D b: {// keep open c: int } } z: a.b z: d: 3 // allow this } reclose3: { #Step: { (#A | #B) #Common } #Common: { Name: string } #A: { #Common Something: int } #B: { #Common Else: int } x: #Step x: #A & { Name: "a" Something: 4 } } -- out/eval/stats -- Leaks: 0 Freed: 63 Reused: 56 Allocs: 7 Retain: 6 Unifications: 59 Conjuncts: 124 Disjuncts: 69 -- out/evalalpha -- Errors: recloseSimple.a.b: field not allowed: ./in.cue:17:6 ./in.cue:17:15 reclose1.z.d: field not allowed: ./in.cue:33:5 ./in.cue:34:5 Result: (_|_){ // [eval] deployment: (struct){ foo: (#struct){ spec: (#struct){ replicas: (int){ 1 } } } } #Deployment: (#struct){ spec: ~(#Spec) } #Spec: (#struct){ replicas: (int){ int } } #TypeMeta: (#struct){ } recloseSimple: (_|_){ // [eval] #foo: (#struct){ } a: (_|_){ // [eval] b: (_|_){ // [eval] recloseSimple.a.b: field not allowed: // ./in.cue:17:6 // ./in.cue:17:15 } } } reclose1: (_|_){ // [eval] #D: (#struct){ x: (int){ int } y: (int){ int } } #a: (#struct){ b: (#struct){ c: (int){ int } } x: (int){ int } y: (int){ int } } z: (_|_){ // [eval] d: (_|_){ // [eval] reclose1.z.d: field not allowed: // ./in.cue:33:5 // ./in.cue:34:5 } c: (int){ int } } } reclose2: (struct){ #D: (#struct){ x: (int){ int } y: (int){ int } } a: (#struct){ b: (struct){ c: (int){ int } } x: (int){ int } y: (int){ int } } z: (struct){ d: (int){ 3 } c: (int){ int } } } reclose3: (struct){ #Step: (#struct){ |((#struct){ Name: (string){ string } Something: (int){ int } }, (#struct){ Name: (string){ string } Else: (int){ int } }) } #Common: (#struct){ Name: (string){ string } } #A: (#struct){ Something: (int){ int } Name: (string){ string } } #B: (#struct){ Else: (int){ int } Name: (string){ string } } x: (#struct){ Name: (string){ "a" } Something: (int){ 4 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,13 +1,10 @@ Errors: -reclose1.z.d: field not allowed: - ./in.cue:28:6 - ./in.cue:33:5 - ./in.cue:34:5 recloseSimple.a.b: field not allowed: - ./in.cue:16:8 - ./in.cue:17:5 ./in.cue:17:6 ./in.cue:17:15 +reclose1.z.d: field not allowed: + ./in.cue:33:5 + ./in.cue:34:5 Result: (_|_){ @@ -20,9 +17,7 @@ } } #Deployment: (#struct){ - spec: (#struct){ - replicas: (int){ int } - } + spec: ~(#Spec) } #Spec: (#struct){ replicas: (int){ int } @@ -37,8 +32,6 @@ // [eval] b: (_|_){ // [eval] recloseSimple.a.b: field not allowed: - // ./in.cue:16:8 - // ./in.cue:17:5 // ./in.cue:17:6 // ./in.cue:17:15 } @@ -51,21 +44,20 @@ y: (int){ int } } #a: (#struct){ - x: (int){ int } - y: (int){ int } b: (#struct){ c: (int){ int } } + x: (int){ int } + y: (int){ int } } z: (_|_){ // [eval] - c: (int){ int } d: (_|_){ // [eval] reclose1.z.d: field not allowed: - // ./in.cue:28:6 // ./in.cue:33:5 // ./in.cue:34:5 } + c: (int){ int } } } reclose2: (struct){ @@ -74,15 +66,15 @@ y: (int){ int } } a: (#struct){ - x: (int){ int } - y: (int){ int } b: (struct){ c: (int){ int } } + x: (int){ int } + y: (int){ int } } z: (struct){ - c: (int){ int } d: (int){ 3 } + c: (int){ int } } } reclose3: (struct){ @@ -97,12 +89,12 @@ Name: (string){ string } } #A: (#struct){ - Name: (string){ string } Something: (int){ int } + Name: (string){ string } } #B: (#struct){ - Name: (string){ string } Else: (int){ int } + Name: (string){ string } } x: (#struct){ Name: (string){ "a" } -- diff/todo/p3 -- Reordering Missing error positions -- out/eval -- Errors: reclose1.z.d: field not allowed: ./in.cue:28:6 ./in.cue:33:5 ./in.cue:34:5 recloseSimple.a.b: field not allowed: ./in.cue:16:8 ./in.cue:17:5 ./in.cue:17:6 ./in.cue:17:15 Result: (_|_){ // [eval] deployment: (struct){ foo: (#struct){ spec: (#struct){ replicas: (int){ 1 } } } } #Deployment: (#struct){ spec: (#struct){ replicas: (int){ int } } } #Spec: (#struct){ replicas: (int){ int } } #TypeMeta: (#struct){ } recloseSimple: (_|_){ // [eval] #foo: (#struct){ } a: (_|_){ // [eval] b: (_|_){ // [eval] recloseSimple.a.b: field not allowed: // ./in.cue:16:8 // ./in.cue:17:5 // ./in.cue:17:6 // ./in.cue:17:15 } } } reclose1: (_|_){ // [eval] #D: (#struct){ x: (int){ int } y: (int){ int } } #a: (#struct){ x: (int){ int } y: (int){ int } b: (#struct){ c: (int){ int } } } z: (_|_){ // [eval] c: (int){ int } d: (_|_){ // [eval] reclose1.z.d: field not allowed: // ./in.cue:28:6 // ./in.cue:33:5 // ./in.cue:34:5 } } } reclose2: (struct){ #D: (#struct){ x: (int){ int } y: (int){ int } } a: (#struct){ x: (int){ int } y: (int){ int } b: (struct){ c: (int){ int } } } z: (struct){ c: (int){ int } d: (int){ 3 } } } reclose3: (struct){ #Step: (#struct){ |((#struct){ Name: (string){ string } Something: (int){ int } }, (#struct){ Name: (string){ string } Else: (int){ int } }) } #Common: (#struct){ Name: (string){ string } } #A: (#struct){ Name: (string){ string } Something: (int){ int } } #B: (#struct){ Name: (string){ string } Else: (int){ int } } x: (#struct){ Name: (string){ "a" } Something: (int){ 4 } } } } -- out/compile -- --- in.cue { deployment: { [string]: 〈1;#Deployment〉 } deployment: { foo: { spec: { replicas: 1 } } } #Deployment: { 〈1;#TypeMeta〉 spec: 〈1;#Spec〉 } #Spec: { replicas: int } #TypeMeta: {} recloseSimple: { #foo: {} a: ({ 〈1;#foo〉 } & { b: int }) } reclose1: { #D: { x: int y: int } #a: { 〈1;#D〉 b: { c: int } } z: 〈0;#a〉.b z: { d: 3 } } reclose2: { #D: { x: int y: int } a: { 〈1;#D〉 b: { c: int } } z: 〈0;a〉.b z: { d: 3 } } reclose3: { #Step: { (〈1;#A〉|〈1;#B〉) 〈1;#Common〉 } #Common: { Name: string } #A: { 〈1;#Common〉 Something: int } #B: { 〈1;#Common〉 Else: int } x: 〈0;#Step〉 x: (〈0;#A〉 & { Name: "a" Something: 4 }) } } cue-lang-cue-db9cc73/cue/testdata/definitions/fields.txtar000066400000000000000000001073411474664451600237400ustar00rootroot00000000000000// Tests fields.go -- in.cue -- // TODO: reorganize ordered on what is tested by name. E.g. // insertion: longPath: ok: p1: { // a: .... @fail() // } ok: t1: { c: #R c: [{b: int}] #R: [...] } ok: t2: { #A: _ l: #A l: f: "hi" } ok: t3: { #A: f: {...} #A1: { #A } s: [string]: #A1 s: foo: f: d: foo: 1 } ok: t4: { #T: { a: b: 1 } W: { {#T} b: c: 2 } } ok: t5: { // TODO: this should pass #A: { Common _ } Common: { } x: #A x: c: int } ok: t6: { #A: { Common ... } Common: { } x: #A x: c: int } ok: t7: { a: {#A, #B} #A: b: f: 1 #B: b: g: 1 } ok: t8: { // TODO: this should pass foo: #X #X: { a: b: c: C: 1 for k, _ in a { // dynamic field causes insertion one level higher. This causes // b to be inserted in a, after it has been referenced. a: (k): c: D: 2 } } } ok: t9: { c: #R c: [{b: int}] #R: [...] } ok: t10: { #A: _ // top should allow everything l: #A l: f: "hi" } ok: t11: { // indirections #A: f: {...} #A1: { #A } s: [string]: #A1 s: foo: f: d: foo: "bar" // should pass } ok: t12: { // nested embedding #T: { a: b: 1 } W: { {#T} b: c: 2 } } ok: t13: { // TODO: this should pass // top opens up #A: { Common _ } Common: { } x: #A x: c: int } ok: t14: { // ellipsis opens up #A: { Common ... } Common: { } x: #A x: c: int } err: t1: { #D: _ & {a: 2} a: #D a: disallowed: 1 } err: t2: { #S: { { c: d: 1 } } V: #S V: { c: e: 1 } } err: t3: p1: { #D: {} a: #D a: c: "C" } err: t3: p2: { #D: b: {} a: #D a: b: c: "C" } err: t4: { a: #A #A: b: f: 1 a: b: h: 1 } err: t5: { // TODO: this should fail a: {#A, #B} #A: b: f: 1 #B: b: g: 1 b: a b: b: h: 1 // only an error here } err: t6: { // TODO: this should fail a: {#A, #B} #A: b: c: d: e: f: 1 #B: b: c: d: e: g: 1 b: a b: b: c: d: e: h: 1 // only an error here } err: t7: { #D: _ & {a: 2} a: #D a: b: 1 // FAIL } err: t8: { // nested embedding #S: { { c: d: 1 } } V: #S V: { c: e: 1 } // Should fail } -- issue1830.cue -- issue1830: { #x: { y: { z?: { name: string } } } egs: { x1: (#x & {y: z: _}).y.z & { name: "blah" age1: 5 } x2: (#x.y & {z: _}).z & { name: "blah" age2: 5 } } } -- issue3491.cue -- issue3491: { #Schema: field?: {} a: #Schema & { field: {} } a: b b: #Extra: {} } -- out/eval/stats -- Leaks: 3 Freed: 218 Reused: 211 Allocs: 10 Retain: 20 Unifications: 221 Conjuncts: 402 Disjuncts: 238 -- out/evalalpha -- Errors: err.t2.V.c.e: field not allowed: ./in.cue:136:10 err.t3.p2.a.b.c: field not allowed: ./in.cue:148:8 err.t4.a.b.h: field not allowed: ./in.cue:154:8 err.t5.b.b.h: field not allowed: ./in.cue:163:8 err.t6.b.b.c.d.e.h: field not allowed: ./in.cue:172:17 err.t8.V.c.e: field not allowed: ./in.cue:185:10 issue1830.egs.x1.age1: field not allowed: ./issue1830.cue:13:4 issue1830.egs.x2.age2: field not allowed: ./issue1830.cue:17:4 ok.t5.x.c: field not allowed: ./in.cue:36:3 ./in.cue:41:5 ok.t13.x.c: field not allowed: ./in.cue:107:3 ./in.cue:112:5 err.t1.a.disallowed: field not allowed: ./in.cue:129:5 ./in.cue:130:5 err.t3.p1.a.c: field not allowed: ./in.cue:141:5 ./in.cue:142:5 err.t7.a.b: field not allowed: ./in.cue:177:5 ./in.cue:178:5 Result: (_|_){ // [eval] ok: (_|_){ // [eval] t1: (struct){ c: (#list){ 0: (#struct){ b: (int){ int } } } #R: (list){ } } t2: (struct){ #A: (_){ _ } l: (#struct){ f: (string){ "hi" } } } t3: (struct){ #A: (#struct){ f: (#struct){ } } #A1: (#struct){ f: (#struct){ } } s: (struct){ foo: (#struct){ f: (#struct){ d: (struct){ foo: (int){ 1 } } } } } } t4: (struct){ #T: (#struct){ a: (#struct){ b: (int){ 1 } } } W: (#struct){ b: (struct){ c: (int){ 2 } } a: (#struct){ b: (int){ 1 } } } } t5: (_|_){ // [eval] #A: (#struct){ } Common: (struct){ } x: (_|_){ // [eval] c: (_|_){ // [eval] ok.t5.x.c: field not allowed: // ./in.cue:36:3 // ./in.cue:41:5 } } } t6: (struct){ #A: (#struct){ } Common: (struct){ } x: (#struct){ c: (int){ int } } } t7: (struct){ a: (#struct){ b: (#struct){ f: (int){ 1 } g: (int){ 1 } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } } #B: (#struct){ b: (#struct){ g: (int){ 1 } } } } t8: (struct){ foo: ~(ok.t8.#X) #X: (#struct){ a: (#struct){ b: (#struct){ c: (#struct){ C: (int){ 1 } D: (int){ 2 } } } } } } t9: (struct){ c: (#list){ 0: (#struct){ b: (int){ int } } } #R: (list){ } } t10: (struct){ #A: (_){ _ } l: (#struct){ f: (string){ "hi" } } } t11: (struct){ #A: (#struct){ f: (#struct){ } } #A1: (#struct){ f: (#struct){ } } s: (struct){ foo: (#struct){ f: (#struct){ d: (struct){ foo: (string){ "bar" } } } } } } t12: (struct){ #T: (#struct){ a: (#struct){ b: (int){ 1 } } } W: (#struct){ b: (struct){ c: (int){ 2 } } a: (#struct){ b: (int){ 1 } } } } t13: (_|_){ // [eval] #A: (#struct){ } Common: (struct){ } x: (_|_){ // [eval] c: (_|_){ // [eval] ok.t13.x.c: field not allowed: // ./in.cue:107:3 // ./in.cue:112:5 } } } t14: (struct){ #A: (#struct){ } Common: (struct){ } x: (#struct){ c: (int){ int } } } } err: (_|_){ // [eval] t1: (_|_){ // [eval] #D: (#struct){ a: (int){ 2 } } a: (_|_){ // [eval] disallowed: (_|_){ // [eval] err.t1.a.disallowed: field not allowed: // ./in.cue:129:5 // ./in.cue:130:5 } a: (int){ 2 } } } t2: (_|_){ // [eval] #S: (#struct){ c: (#struct){ d: (int){ 1 } } } V: (_|_){ // [eval] c: (_|_){ // [eval] e: (_|_){ // [eval] err.t2.V.c.e: field not allowed: // ./in.cue:136:10 } d: (int){ 1 } } } } t3: (_|_){ // [eval] p1: (_|_){ // [eval] #D: (#struct){ } a: (_|_){ // [eval] c: (_|_){ // [eval] err.t3.p1.a.c: field not allowed: // ./in.cue:141:5 // ./in.cue:142:5 } } } p2: (_|_){ // [eval] #D: (#struct){ b: (#struct){ } } a: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] err.t3.p2.a.b.c: field not allowed: // ./in.cue:148:8 } } } } } t4: (_|_){ // [eval] a: (_|_){ // [eval] b: (_|_){ // [eval] h: (_|_){ // [eval] err.t4.a.b.h: field not allowed: // ./in.cue:154:8 } f: (int){ 1 } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } } } t5: (_|_){ // [eval] a: (#struct){ b: (#struct){ f: (int){ 1 } g: (int){ 1 } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } } #B: (#struct){ b: (#struct){ g: (int){ 1 } } } b: (_|_){ // [eval] b: (_|_){ // [eval] h: (_|_){ // [eval] err.t5.b.b.h: field not allowed: // ./in.cue:163:8 } f: (int){ 1 } g: (int){ 1 } } } } t6: (_|_){ // [eval] a: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ e: (#struct){ f: (int){ 1 } g: (int){ 1 } } } } } } #A: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ e: (#struct){ f: (int){ 1 } } } } } } #B: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ e: (#struct){ g: (int){ 1 } } } } } } b: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] d: (_|_){ // [eval] e: (_|_){ // [eval] h: (_|_){ // [eval] err.t6.b.b.c.d.e.h: field not allowed: // ./in.cue:172:17 } f: (int){ 1 } g: (int){ 1 } } } } } } } t7: (_|_){ // [eval] #D: (#struct){ a: (int){ 2 } } a: (_|_){ // [eval] b: (_|_){ // [eval] err.t7.a.b: field not allowed: // ./in.cue:177:5 // ./in.cue:178:5 } a: (int){ 2 } } } t8: (_|_){ // [eval] #S: (#struct){ c: (#struct){ d: (int){ 1 } } } V: (_|_){ // [eval] c: (_|_){ // [eval] e: (_|_){ // [eval] err.t8.V.c.e: field not allowed: // ./in.cue:185:10 } d: (int){ 1 } } } } } issue1830: (_|_){ // [eval] #x: (#struct){ y: (#struct){ z?: (#struct){ name: (string){ string } } } } egs: (_|_){ // [eval] x1: (_|_){ // [eval] name: (string){ "blah" } age1: (_|_){ // [eval] issue1830.egs.x1.age1: field not allowed: // ./issue1830.cue:13:4 } } x2: (_|_){ // [eval] name: (string){ "blah" } age2: (_|_){ // [eval] issue1830.egs.x2.age2: field not allowed: // ./issue1830.cue:17:4 } } } } issue3491: (struct){ #Schema: (#struct){ field?: (#struct){ } } a: (#struct){ field: (#struct){ } #Extra: (#struct){ } } b: (struct){ #Extra: (#struct){ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,60 +1,35 @@ Errors: -err.t1.a.disallowed: field not allowed: - ./in.cue:128:10 - ./in.cue:129:5 - ./in.cue:130:5 err.t2.V.c.e: field not allowed: - ./in.cue:134:8 - ./in.cue:134:13 - ./in.cue:135:5 ./in.cue:136:10 -err.t3.p1.a.c: field not allowed: - ./in.cue:140:6 - ./in.cue:141:5 - ./in.cue:142:5 err.t3.p2.a.b.c: field not allowed: - ./in.cue:146:9 - ./in.cue:147:5 ./in.cue:148:8 err.t4.a.b.h: field not allowed: - ./in.cue:152:5 - ./in.cue:153:9 ./in.cue:154:8 err.t5.b.b.h: field not allowed: - ./in.cue:159:6 - ./in.cue:159:10 - ./in.cue:160:9 - ./in.cue:161:9 - ./in.cue:162:5 ./in.cue:163:8 err.t6.b.b.c.d.e.h: field not allowed: - ./in.cue:168:6 - ./in.cue:168:10 - ./in.cue:169:18 - ./in.cue:170:18 - ./in.cue:171:5 ./in.cue:172:17 -err.t7.a.b: field not allowed: - ./in.cue:176:10 - ./in.cue:177:5 - ./in.cue:178:5 err.t8.V.c.e: field not allowed: - ./in.cue:183:8 - ./in.cue:183:13 - ./in.cue:184:5 ./in.cue:185:10 -ok.t13.x.c: field not allowed: - ./in.cue:106:6 - ./in.cue:107:3 - ./in.cue:110:10 - ./in.cue:111:5 - ./in.cue:112:5 +issue1830.egs.x1.age1: field not allowed: + ./issue1830.cue:13:4 +issue1830.egs.x2.age2: field not allowed: + ./issue1830.cue:17:4 ok.t5.x.c: field not allowed: - ./in.cue:35:6 ./in.cue:36:3 - ./in.cue:39:10 - ./in.cue:40:5 ./in.cue:41:5 +ok.t13.x.c: field not allowed: + ./in.cue:107:3 + ./in.cue:112:5 +err.t1.a.disallowed: field not allowed: + ./in.cue:129:5 + ./in.cue:130:5 +err.t3.p1.a.c: field not allowed: + ./in.cue:141:5 + ./in.cue:142:5 +err.t7.a.b: field not allowed: + ./in.cue:177:5 + ./in.cue:178:5 Result: (_|_){ @@ -63,7 +38,7 @@ // [eval] t1: (struct){ c: (#list){ - 0: (struct){ + 0: (#struct){ b: (int){ int } } } @@ -72,7 +47,7 @@ } t2: (struct){ #A: (_){ _ } - l: (struct){ + l: (#struct){ f: (string){ "hi" } } } @@ -102,11 +77,11 @@ } } W: (#struct){ - a: (#struct){ - b: (int){ 1 } - } - b: (struct){ - c: (int){ 2 } + b: (struct){ + c: (int){ 2 } + } + a: (#struct){ + b: (int){ 1 } } } } @@ -120,10 +95,7 @@ // [eval] c: (_|_){ // [eval] ok.t5.x.c: field not allowed: - // ./in.cue:35:6 // ./in.cue:36:3 - // ./in.cue:39:10 - // ./in.cue:40:5 // ./in.cue:41:5 } } @@ -156,16 +128,7 @@ } } t8: (struct){ - foo: (#struct){ - a: (#struct){ - b: (#struct){ - c: (#struct){ - C: (int){ 1 } - D: (int){ 2 } - } - } - } - } + foo: ~(ok.t8.#X) #X: (#struct){ a: (#struct){ b: (#struct){ @@ -179,7 +142,7 @@ } t9: (struct){ c: (#list){ - 0: (struct){ + 0: (#struct){ b: (int){ int } } } @@ -188,7 +151,7 @@ } t10: (struct){ #A: (_){ _ } - l: (struct){ + l: (#struct){ f: (string){ "hi" } } } @@ -218,11 +181,11 @@ } } W: (#struct){ - a: (#struct){ - b: (int){ 1 } - } - b: (struct){ - c: (int){ 2 } + b: (struct){ + c: (int){ 2 } + } + a: (#struct){ + b: (int){ 1 } } } } @@ -236,10 +199,7 @@ // [eval] c: (_|_){ // [eval] ok.t13.x.c: field not allowed: - // ./in.cue:106:6 // ./in.cue:107:3 - // ./in.cue:110:10 - // ./in.cue:111:5 // ./in.cue:112:5 } } @@ -263,13 +223,12 @@ } a: (_|_){ // [eval] - a: (int){ 2 } disallowed: (_|_){ // [eval] err.t1.a.disallowed: field not allowed: - // ./in.cue:128:10 // ./in.cue:129:5 // ./in.cue:130:5 } + a: (int){ 2 } } } t2: (_|_){ @@ -283,14 +242,11 @@ // [eval] c: (_|_){ // [eval] - d: (int){ 1 } e: (_|_){ // [eval] err.t2.V.c.e: field not allowed: - // ./in.cue:134:8 - // ./in.cue:134:13 - // ./in.cue:135:5 // ./in.cue:136:10 } + d: (int){ 1 } } } } @@ -304,7 +260,6 @@ // [eval] c: (_|_){ // [eval] err.t3.p1.a.c: field not allowed: - // ./in.cue:140:6 // ./in.cue:141:5 // ./in.cue:142:5 } @@ -322,8 +277,6 @@ // [eval] c: (_|_){ // [eval] err.t3.p2.a.b.c: field not allowed: - // ./in.cue:146:9 - // ./in.cue:147:5 // ./in.cue:148:8 } } @@ -336,54 +289,47 @@ // [eval] b: (_|_){ // [eval] - f: (int){ 1 } h: (_|_){ // [eval] err.t4.a.b.h: field not allowed: - // ./in.cue:152:5 - // ./in.cue:153:9 // ./in.cue:154:8 } - } - } - #A: (#struct){ - b: (#struct){ - f: (int){ 1 } - } - } - } - t5: (_|_){ - // [eval] - a: (#struct){ - b: (#struct){ - f: (int){ 1 } - g: (int){ 1 } - } - } - #A: (#struct){ - b: (#struct){ - f: (int){ 1 } - } - } - #B: (#struct){ - b: (#struct){ - g: (int){ 1 } - } - } - b: (_|_){ - // [eval] - b: (_|_){ - // [eval] - f: (int){ 1 } - g: (int){ 1 } + f: (int){ 1 } + } + } + #A: (#struct){ + b: (#struct){ + f: (int){ 1 } + } + } + } + t5: (_|_){ + // [eval] + a: (#struct){ + b: (#struct){ + f: (int){ 1 } + g: (int){ 1 } + } + } + #A: (#struct){ + b: (#struct){ + f: (int){ 1 } + } + } + #B: (#struct){ + b: (#struct){ + g: (int){ 1 } + } + } + b: (_|_){ + // [eval] + b: (_|_){ + // [eval] h: (_|_){ // [eval] err.t5.b.b.h: field not allowed: - // ./in.cue:159:6 - // ./in.cue:159:10 - // ./in.cue:160:9 - // ./in.cue:161:9 - // ./in.cue:162:5 // ./in.cue:163:8 } + f: (int){ 1 } + g: (int){ 1 } } } } @@ -433,17 +379,12 @@ // [eval] e: (_|_){ // [eval] - f: (int){ 1 } - g: (int){ 1 } h: (_|_){ // [eval] err.t6.b.b.c.d.e.h: field not allowed: - // ./in.cue:168:6 - // ./in.cue:168:10 - // ./in.cue:169:18 - // ./in.cue:170:18 - // ./in.cue:171:5 // ./in.cue:172:17 } + f: (int){ 1 } + g: (int){ 1 } } } } @@ -457,13 +398,12 @@ } a: (_|_){ // [eval] - a: (int){ 2 } b: (_|_){ // [eval] err.t7.a.b: field not allowed: - // ./in.cue:176:10 // ./in.cue:177:5 // ./in.cue:178:5 } + a: (int){ 2 } } } t8: (_|_){ @@ -477,19 +417,17 @@ // [eval] c: (_|_){ // [eval] - d: (int){ 1 } e: (_|_){ // [eval] err.t8.V.c.e: field not allowed: - // ./in.cue:183:8 - // ./in.cue:183:13 - // ./in.cue:184:5 // ./in.cue:185:10 } - } - } - } - } - issue1830: (struct){ + d: (int){ 1 } + } + } + } + } + issue1830: (_|_){ + // [eval] #x: (#struct){ y: (#struct){ z?: (#struct){ @@ -497,14 +435,23 @@ } } } - egs: (struct){ - x1: (struct){ - name: (string){ "blah" } - age1: (int){ 5 } - } - x2: (struct){ - name: (string){ "blah" } - age2: (int){ 5 } + egs: (_|_){ + // [eval] + x1: (_|_){ + // [eval] + name: (string){ "blah" } + age1: (_|_){ + // [eval] issue1830.egs.x1.age1: field not allowed: + // ./issue1830.cue:13:4 + } + } + x2: (_|_){ + // [eval] + name: (string){ "blah" } + age2: (_|_){ + // [eval] issue1830.egs.x2.age2: field not allowed: + // ./issue1830.cue:17:4 + } } } } -- diff/todo/p2 -- ok.t1.c.0: closedness probably incorrect: #R defines elements as type "top", which are not closed by definition. Probably does not matter for evaluation, as it will be determined to be "closed", but allowing all attributes. ok.t(9|10).c.0: same issue as ok.t1.c.0. ok.t2.l: same issue: top is marked as "closed", even though it will allow all values. Probably just a matter of difference in debugging output and not evaluation semantics. all: error positions and reordering. -- diff/explanation -- ok.t5 and ok.t13 retain semantics of v0.6 for now. issue1830: the new evaluator correctly rejects inserting new fields in a closed struct -- out/eval -- Errors: err.t1.a.disallowed: field not allowed: ./in.cue:128:10 ./in.cue:129:5 ./in.cue:130:5 err.t2.V.c.e: field not allowed: ./in.cue:134:8 ./in.cue:134:13 ./in.cue:135:5 ./in.cue:136:10 err.t3.p1.a.c: field not allowed: ./in.cue:140:6 ./in.cue:141:5 ./in.cue:142:5 err.t3.p2.a.b.c: field not allowed: ./in.cue:146:9 ./in.cue:147:5 ./in.cue:148:8 err.t4.a.b.h: field not allowed: ./in.cue:152:5 ./in.cue:153:9 ./in.cue:154:8 err.t5.b.b.h: field not allowed: ./in.cue:159:6 ./in.cue:159:10 ./in.cue:160:9 ./in.cue:161:9 ./in.cue:162:5 ./in.cue:163:8 err.t6.b.b.c.d.e.h: field not allowed: ./in.cue:168:6 ./in.cue:168:10 ./in.cue:169:18 ./in.cue:170:18 ./in.cue:171:5 ./in.cue:172:17 err.t7.a.b: field not allowed: ./in.cue:176:10 ./in.cue:177:5 ./in.cue:178:5 err.t8.V.c.e: field not allowed: ./in.cue:183:8 ./in.cue:183:13 ./in.cue:184:5 ./in.cue:185:10 ok.t13.x.c: field not allowed: ./in.cue:106:6 ./in.cue:107:3 ./in.cue:110:10 ./in.cue:111:5 ./in.cue:112:5 ok.t5.x.c: field not allowed: ./in.cue:35:6 ./in.cue:36:3 ./in.cue:39:10 ./in.cue:40:5 ./in.cue:41:5 Result: (_|_){ // [eval] ok: (_|_){ // [eval] t1: (struct){ c: (#list){ 0: (struct){ b: (int){ int } } } #R: (list){ } } t2: (struct){ #A: (_){ _ } l: (struct){ f: (string){ "hi" } } } t3: (struct){ #A: (#struct){ f: (#struct){ } } #A1: (#struct){ f: (#struct){ } } s: (struct){ foo: (#struct){ f: (#struct){ d: (struct){ foo: (int){ 1 } } } } } } t4: (struct){ #T: (#struct){ a: (#struct){ b: (int){ 1 } } } W: (#struct){ a: (#struct){ b: (int){ 1 } } b: (struct){ c: (int){ 2 } } } } t5: (_|_){ // [eval] #A: (#struct){ } Common: (struct){ } x: (_|_){ // [eval] c: (_|_){ // [eval] ok.t5.x.c: field not allowed: // ./in.cue:35:6 // ./in.cue:36:3 // ./in.cue:39:10 // ./in.cue:40:5 // ./in.cue:41:5 } } } t6: (struct){ #A: (#struct){ } Common: (struct){ } x: (#struct){ c: (int){ int } } } t7: (struct){ a: (#struct){ b: (#struct){ f: (int){ 1 } g: (int){ 1 } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } } #B: (#struct){ b: (#struct){ g: (int){ 1 } } } } t8: (struct){ foo: (#struct){ a: (#struct){ b: (#struct){ c: (#struct){ C: (int){ 1 } D: (int){ 2 } } } } } #X: (#struct){ a: (#struct){ b: (#struct){ c: (#struct){ C: (int){ 1 } D: (int){ 2 } } } } } } t9: (struct){ c: (#list){ 0: (struct){ b: (int){ int } } } #R: (list){ } } t10: (struct){ #A: (_){ _ } l: (struct){ f: (string){ "hi" } } } t11: (struct){ #A: (#struct){ f: (#struct){ } } #A1: (#struct){ f: (#struct){ } } s: (struct){ foo: (#struct){ f: (#struct){ d: (struct){ foo: (string){ "bar" } } } } } } t12: (struct){ #T: (#struct){ a: (#struct){ b: (int){ 1 } } } W: (#struct){ a: (#struct){ b: (int){ 1 } } b: (struct){ c: (int){ 2 } } } } t13: (_|_){ // [eval] #A: (#struct){ } Common: (struct){ } x: (_|_){ // [eval] c: (_|_){ // [eval] ok.t13.x.c: field not allowed: // ./in.cue:106:6 // ./in.cue:107:3 // ./in.cue:110:10 // ./in.cue:111:5 // ./in.cue:112:5 } } } t14: (struct){ #A: (#struct){ } Common: (struct){ } x: (#struct){ c: (int){ int } } } } err: (_|_){ // [eval] t1: (_|_){ // [eval] #D: (#struct){ a: (int){ 2 } } a: (_|_){ // [eval] a: (int){ 2 } disallowed: (_|_){ // [eval] err.t1.a.disallowed: field not allowed: // ./in.cue:128:10 // ./in.cue:129:5 // ./in.cue:130:5 } } } t2: (_|_){ // [eval] #S: (#struct){ c: (#struct){ d: (int){ 1 } } } V: (_|_){ // [eval] c: (_|_){ // [eval] d: (int){ 1 } e: (_|_){ // [eval] err.t2.V.c.e: field not allowed: // ./in.cue:134:8 // ./in.cue:134:13 // ./in.cue:135:5 // ./in.cue:136:10 } } } } t3: (_|_){ // [eval] p1: (_|_){ // [eval] #D: (#struct){ } a: (_|_){ // [eval] c: (_|_){ // [eval] err.t3.p1.a.c: field not allowed: // ./in.cue:140:6 // ./in.cue:141:5 // ./in.cue:142:5 } } } p2: (_|_){ // [eval] #D: (#struct){ b: (#struct){ } } a: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] err.t3.p2.a.b.c: field not allowed: // ./in.cue:146:9 // ./in.cue:147:5 // ./in.cue:148:8 } } } } } t4: (_|_){ // [eval] a: (_|_){ // [eval] b: (_|_){ // [eval] f: (int){ 1 } h: (_|_){ // [eval] err.t4.a.b.h: field not allowed: // ./in.cue:152:5 // ./in.cue:153:9 // ./in.cue:154:8 } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } } } t5: (_|_){ // [eval] a: (#struct){ b: (#struct){ f: (int){ 1 } g: (int){ 1 } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } } #B: (#struct){ b: (#struct){ g: (int){ 1 } } } b: (_|_){ // [eval] b: (_|_){ // [eval] f: (int){ 1 } g: (int){ 1 } h: (_|_){ // [eval] err.t5.b.b.h: field not allowed: // ./in.cue:159:6 // ./in.cue:159:10 // ./in.cue:160:9 // ./in.cue:161:9 // ./in.cue:162:5 // ./in.cue:163:8 } } } } t6: (_|_){ // [eval] a: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ e: (#struct){ f: (int){ 1 } g: (int){ 1 } } } } } } #A: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ e: (#struct){ f: (int){ 1 } } } } } } #B: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ e: (#struct){ g: (int){ 1 } } } } } } b: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] d: (_|_){ // [eval] e: (_|_){ // [eval] f: (int){ 1 } g: (int){ 1 } h: (_|_){ // [eval] err.t6.b.b.c.d.e.h: field not allowed: // ./in.cue:168:6 // ./in.cue:168:10 // ./in.cue:169:18 // ./in.cue:170:18 // ./in.cue:171:5 // ./in.cue:172:17 } } } } } } } t7: (_|_){ // [eval] #D: (#struct){ a: (int){ 2 } } a: (_|_){ // [eval] a: (int){ 2 } b: (_|_){ // [eval] err.t7.a.b: field not allowed: // ./in.cue:176:10 // ./in.cue:177:5 // ./in.cue:178:5 } } } t8: (_|_){ // [eval] #S: (#struct){ c: (#struct){ d: (int){ 1 } } } V: (_|_){ // [eval] c: (_|_){ // [eval] d: (int){ 1 } e: (_|_){ // [eval] err.t8.V.c.e: field not allowed: // ./in.cue:183:8 // ./in.cue:183:13 // ./in.cue:184:5 // ./in.cue:185:10 } } } } } issue1830: (struct){ #x: (#struct){ y: (#struct){ z?: (#struct){ name: (string){ string } } } } egs: (struct){ x1: (struct){ name: (string){ "blah" } age1: (int){ 5 } } x2: (struct){ name: (string){ "blah" } age2: (int){ 5 } } } } issue3491: (struct){ #Schema: (#struct){ field?: (#struct){ } } a: (#struct){ field: (#struct){ } #Extra: (#struct){ } } b: (struct){ #Extra: (#struct){ } } } } -- out/compile -- --- in.cue { ok: { t1: { c: 〈0;#R〉 c: [ { b: int }, ] #R: [ ..., ] } } ok: { t2: { #A: _ l: 〈0;#A〉 l: { f: "hi" } } } ok: { t3: { #A: { f: { ... } } #A1: { 〈1;#A〉 } s: { [string]: 〈1;#A1〉 } s: { foo: { f: { d: { foo: 1 } } } } } } ok: { t4: { #T: { a: { b: 1 } } W: { { 〈2;#T〉 } b: { c: 2 } } } } ok: { t5: { #A: { 〈1;Common〉 _ } Common: {} x: 〈0;#A〉 x: { c: int } } } ok: { t6: { #A: { 〈1;Common〉 ... } Common: {} x: 〈0;#A〉 x: { c: int } } } ok: { t7: { a: { 〈1;#A〉 〈1;#B〉 } #A: { b: { f: 1 } } #B: { b: { g: 1 } } } } ok: { t8: { foo: 〈0;#X〉 #X: { a: { b: { c: { C: 1 } } } for k, _ in 〈0;a〉 { a: { 〈2;k〉: { c: { D: 2 } } } } } } } ok: { t9: { c: 〈0;#R〉 c: [ { b: int }, ] #R: [ ..., ] } } ok: { t10: { #A: _ l: 〈0;#A〉 l: { f: "hi" } } } ok: { t11: { #A: { f: { ... } } #A1: { 〈1;#A〉 } s: { [string]: 〈1;#A1〉 } s: { foo: { f: { d: { foo: "bar" } } } } } } ok: { t12: { #T: { a: { b: 1 } } W: { { 〈2;#T〉 } b: { c: 2 } } } } ok: { t13: { #A: { 〈1;Common〉 _ } Common: {} x: 〈0;#A〉 x: { c: int } } } ok: { t14: { #A: { 〈1;Common〉 ... } Common: {} x: 〈0;#A〉 x: { c: int } } } err: { t1: { #D: (_ & { a: 2 }) a: 〈0;#D〉 a: { disallowed: 1 } } } err: { t2: { #S: { { c: { d: 1 } } } V: 〈0;#S〉 V: { c: { e: 1 } } } } err: { t3: { p1: { #D: {} a: 〈0;#D〉 a: { c: "C" } } } } err: { t3: { p2: { #D: { b: {} } a: 〈0;#D〉 a: { b: { c: "C" } } } } } err: { t4: { a: 〈0;#A〉 #A: { b: { f: 1 } } a: { b: { h: 1 } } } } err: { t5: { a: { 〈1;#A〉 〈1;#B〉 } #A: { b: { f: 1 } } #B: { b: { g: 1 } } b: 〈0;a〉 b: { b: { h: 1 } } } } err: { t6: { a: { 〈1;#A〉 〈1;#B〉 } #A: { b: { c: { d: { e: { f: 1 } } } } } #B: { b: { c: { d: { e: { g: 1 } } } } } b: 〈0;a〉 b: { b: { c: { d: { e: { h: 1 } } } } } } } err: { t7: { #D: (_ & { a: 2 }) a: 〈0;#D〉 a: { b: 1 } } } err: { t8: { #S: { { c: { d: 1 } } } V: 〈0;#S〉 V: { c: { e: 1 } } } } } --- issue1830.cue { issue1830: { #x: { y: { z?: { name: string } } } egs: { x1: ((〈1;#x〉 & { y: { z: _ } }).y.z & { name: "blah" age1: 5 }) x2: ((〈1;#x〉.y & { z: _ }).z & { name: "blah" age2: 5 }) } } } --- issue3491.cue { issue3491: { #Schema: { field?: {} } a: (〈0;#Schema〉 & { field: {} }) a: 〈0;b〉 b: { #Extra: {} } } } cue-lang-cue-db9cc73/cue/testdata/definitions/files.txtar000066400000000000000000000050561474664451600235740ustar00rootroot00000000000000// Treat fields of different files as belonging to the same struct. // This means that a closed embedding in one file should not restrict the // fields of another. -- in.cue -- package foo #theme: { color: string ctermbg: string } dark: #theme & { color: "dark" ctermbg: "239" } light: #theme & { color: "light" ctermbg: "254" } #Config: { console: dark | *light } -- box.cue -- package foo #Config & { console: dark } -- out/eval/stats -- Leaks: 0 Freed: 25 Reused: 19 Allocs: 6 Retain: 1 Unifications: 21 Conjuncts: 69 Disjuncts: 26 -- out/evalalpha -- (#struct){ console: (#struct){ color: (string){ "dark" } ctermbg: (string){ "239" } } #theme: (#struct){ color: (string){ string } ctermbg: (string){ string } } dark: (#struct){ color: (string){ "dark" } ctermbg: (string){ "239" } } light: (#struct){ color: (string){ "light" } ctermbg: (string){ "254" } } #Config: (#struct){ console: (#struct){ |(*(#struct){ color: (string){ "light" } ctermbg: (string){ "254" } }, (#struct){ color: (string){ "dark" } ctermbg: (string){ "239" } }) } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,4 +1,8 @@ (#struct){ + console: (#struct){ + color: (string){ "dark" } + ctermbg: (string){ "239" } + } #theme: (#struct){ color: (string){ string } ctermbg: (string){ string } @@ -20,8 +24,4 @@ ctermbg: (string){ "239" } }) } } - console: (#struct){ - color: (string){ "dark" } - ctermbg: (string){ "239" } - } } -- diff/todo/p3 -- Reordering. -- out/eval -- (#struct){ #theme: (#struct){ color: (string){ string } ctermbg: (string){ string } } dark: (#struct){ color: (string){ "dark" } ctermbg: (string){ "239" } } light: (#struct){ color: (string){ "light" } ctermbg: (string){ "254" } } #Config: (#struct){ console: (#struct){ |(*(#struct){ color: (string){ "light" } ctermbg: (string){ "254" } }, (#struct){ color: (string){ "dark" } ctermbg: (string){ "239" } }) } } console: (#struct){ color: (string){ "dark" } ctermbg: (string){ "239" } } } -- out/compile -- --- box.cue { (〈0;#Config〉 & { console: 〈1;dark〉 }) } --- in.cue { #theme: { color: string ctermbg: string } dark: (〈0;#theme〉 & { color: "dark" ctermbg: "239" }) light: (〈0;#theme〉 & { color: "light" ctermbg: "254" }) #Config: { console: (〈1;dark〉|*〈1;light〉) } } cue-lang-cue-db9cc73/cue/testdata/definitions/hidden.txtar000066400000000000000000000102261474664451600237200ustar00rootroot00000000000000exec cue eval ./pkg:foo -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- package foo import "mod.test/pkg" #def: { _name: d: int } d: pkg.#D & {_name: d: int, _val: f: 4} // TODO: this should fail, as the _name restricting it is in this // package. e: pkg.#D & #def & { // This should fail as c is disallowed by the _name defined // in this package _name: c: int // This should not fail, as this is a different _val _val: g: int } f: pkg.#D & {_val: f: 4} g: f._val -- pkg/bar.cue -- package pkg #D: {_val: f: 3} -- out/eval/stats -- Leaks: 1 Freed: 29 Reused: 24 Allocs: 6 Retain: 2 Unifications: 30 Conjuncts: 40 Disjuncts: 31 -- out/evalalpha -- Errors: e._name.c: field not allowed: ./in.cue:16:9 Result: (_|_){ // [eval] #def: (#struct){ _name(:foo): (#struct){ d: (int){ int } } } d: (#struct){ _name(:foo): (struct){ d: (int){ int } } _val(:foo): (struct){ f: (int){ 4 } } _val(mod.test/pkg): (#struct){ f: (int){ 3 } } } e: (_|_){ // [eval] _name(:foo): (_|_){ // [eval] c: (_|_){ // [eval] e._name.c: field not allowed: // ./in.cue:16:9 } d: (int){ int } } _val(:foo): (struct){ g: (int){ int } } _val(mod.test/pkg): (#struct){ f: (int){ 3 } } } f: (#struct){ _val(:foo): (struct){ f: (int){ 4 } } _val(mod.test/pkg): (#struct){ f: (int){ 3 } } } g: ~(f._val(:foo)) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,5 @@ Errors: e._name.c: field not allowed: - ./in.cue:6:9 - ./in.cue:13:13 ./in.cue:16:9 Result: @@ -13,9 +11,6 @@ } } d: (#struct){ - _val(mod.test/pkg): (#struct){ - f: (int){ 3 } - } _name(:foo): (struct){ d: (int){ int } } @@ -22,35 +17,34 @@ _val(:foo): (struct){ f: (int){ 4 } } + _val(mod.test/pkg): (#struct){ + f: (int){ 3 } + } } e: (_|_){ // [eval] - _val(mod.test/pkg): (#struct){ - f: (int){ 3 } - } _name(:foo): (_|_){ // [eval] - d: (int){ int } c: (_|_){ // [eval] e._name.c: field not allowed: - // ./in.cue:6:9 - // ./in.cue:13:13 // ./in.cue:16:9 } + d: (int){ int } } _val(:foo): (struct){ g: (int){ int } } + _val(mod.test/pkg): (#struct){ + f: (int){ 3 } + } } f: (#struct){ - _val(mod.test/pkg): (#struct){ - f: (int){ 3 } - } - _val(:foo): (struct){ - f: (int){ 4 } - } - } - g: (struct){ - f: (int){ 4 } - } + _val(:foo): (struct){ + f: (int){ 4 } + } + _val(mod.test/pkg): (#struct){ + f: (int){ 3 } + } + } + g: ~(f._val(:foo)) } -- diff/todo/p2 -- Reordering / missing positions. -- out/eval -- Errors: e._name.c: field not allowed: ./in.cue:6:9 ./in.cue:13:13 ./in.cue:16:9 Result: (_|_){ // [eval] #def: (#struct){ _name(:foo): (#struct){ d: (int){ int } } } d: (#struct){ _val(mod.test/pkg): (#struct){ f: (int){ 3 } } _name(:foo): (struct){ d: (int){ int } } _val(:foo): (struct){ f: (int){ 4 } } } e: (_|_){ // [eval] _val(mod.test/pkg): (#struct){ f: (int){ 3 } } _name(:foo): (_|_){ // [eval] d: (int){ int } c: (_|_){ // [eval] e._name.c: field not allowed: // ./in.cue:6:9 // ./in.cue:13:13 // ./in.cue:16:9 } } _val(:foo): (struct){ g: (int){ int } } } f: (#struct){ _val(mod.test/pkg): (#struct){ f: (int){ 3 } } _val(:foo): (struct){ f: (int){ 4 } } } g: (struct){ f: (int){ 4 } } } -- out/compile -- --- in.cue { #def: { _name: { d: int } } d: (〈import;"mod.test/pkg"〉.#D & { _name: { d: int } _val: { f: 4 } }) e: ((〈import;"mod.test/pkg"〉.#D & 〈0;#def〉) & { _name: { c: int } _val: { g: int } }) f: (〈import;"mod.test/pkg"〉.#D & { _val: { f: 4 } }) g: 〈0;f〉._val } cue-lang-cue-db9cc73/cue/testdata/definitions/issue271.txtar000066400000000000000000000031501474664451600240450ustar00rootroot00000000000000-- in.cue -- #T: [_]: _ #T: close({"a": string}) x: #T x: { a: "hello" b: "foo" } -- out/eval/stats -- Leaks: 2 Freed: 6 Reused: 3 Allocs: 5 Retain: 2 Unifications: 8 Conjuncts: 18 Disjuncts: 8 -- out/evalalpha -- Errors: x.b: field not allowed: ./in.cue:2:5 ./in.cue:1:5 ./in.cue:6:2 Result: (_|_){ // [eval] #T: (#struct){ a: (string){ string } } x: (_|_){ // [eval] a: (string){ "hello" } b: (_|_){ // [eval] x.b: field not allowed: // ./in.cue:2:5 // ./in.cue:1:5 // ./in.cue:6:2 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,8 +1,7 @@ Errors: x.b: field not allowed: + ./in.cue:2:5 ./in.cue:1:5 - ./in.cue:2:11 - ./in.cue:3:5 ./in.cue:6:2 Result: @@ -16,9 +15,8 @@ a: (string){ "hello" } b: (_|_){ // [eval] x.b: field not allowed: + // ./in.cue:2:5 // ./in.cue:1:5 - // ./in.cue:2:11 - // ./in.cue:3:5 // ./in.cue:6:2 } } -- diff/todo/p2 -- Positions. -- out/eval -- Errors: x.b: field not allowed: ./in.cue:1:5 ./in.cue:2:11 ./in.cue:3:5 ./in.cue:6:2 Result: (_|_){ // [eval] #T: (#struct){ a: (string){ string } } x: (_|_){ // [eval] a: (string){ "hello" } b: (_|_){ // [eval] x.b: field not allowed: // ./in.cue:1:5 // ./in.cue:2:11 // ./in.cue:3:5 // ./in.cue:6:2 } } } -- out/compile -- --- in.cue { #T: { [_]: _ } #T: close({ a: string }) x: 〈0;#T〉 x: { a: "hello" b: "foo" } } cue-lang-cue-db9cc73/cue/testdata/definitions/issue317.txtar000066400000000000000000000071721474664451600240560ustar00rootroot00000000000000# Allow otherField -- in.cue -- #T: { #Schema: [_]: #D concrete: #Schema } #D: { fieldWithDefault: *0 | int ... } s: #T & { #Schema: { foo: otherField: string } concrete: foo: otherField: "hello" } #Container: { Env: [Name=string]: { name: string value: string } } #Deployment: { #Containers: [Name=string]: #Container containers: [for c in #Containers {c}] // Problem is here. } Something: { #Deployment #Containers: { // Does not allow entries other than value. Either add ... or embed "a thing": Env: foobar: value: "foo" } } x: Something & #Deployment -- out/eval/stats -- Leaks: 0 Freed: 52 Reused: 45 Allocs: 7 Retain: 0 Unifications: 46 Conjuncts: 122 Disjuncts: 52 -- out/eval -- (struct){ #T: (#struct){ #Schema: (#struct){ } concrete: (#struct){ } } #D: (#struct){ fieldWithDefault: (int){ |(*(int){ 0 }, (int){ int }) } } s: (#struct){ #Schema: (#struct){ foo: (#struct){ otherField: (string){ string } fieldWithDefault: (int){ |(*(int){ 0 }, (int){ int }) } } } concrete: (#struct){ foo: (#struct){ otherField: (string){ "hello" } fieldWithDefault: (int){ |(*(int){ 0 }, (int){ int }) } } } } #Container: (#struct){ Env: (#struct){ } } #Deployment: (#struct){ #Containers: (#struct){ } containers: (#list){ } } Something: (#struct){ #Containers: (#struct){ "a thing": (#struct){ Env: (#struct){ foobar: (#struct){ value: (string){ "foo" } name: (string){ string } } } } } containers: (#list){ 0: (#struct){ Env: (#struct){ foobar: (#struct){ value: (string){ "foo" } name: (string){ string } } } } } } x: (#struct){ #Containers: (#struct){ "a thing": (#struct){ Env: (#struct){ foobar: (#struct){ value: (string){ "foo" } name: (string){ string } } } } } containers: (#list){ 0: (#struct){ Env: (#struct){ foobar: (#struct){ value: (string){ "foo" } name: (string){ string } } } } } } } -- out/export -- #T: { #Schema: [_]: #D concrete: #Schema } #D: { fieldWithDefault: *0 | int ... } s: #T & { #Schema: { foo: otherField: string } concrete: foo: otherField: "hello" } #Container: { Env: [Name=string]: { name: string value: string } } #Deployment: { #Containers: [Name=string]: #Container containers: [for c in #Containers {c}] // Problem is here. } Something: { #Deployment #Containers: { // Does not allow entries other than value. Either add ... or embed "a thing": Env: foobar: value: "foo" } } x: Something & #Deployment -- out/compile -- --- in.cue { #T: { #Schema: { [_]: 〈2;#D〉 } concrete: 〈0;#Schema〉 } #D: { fieldWithDefault: (*0|int) ... } s: (〈0;#T〉 & { #Schema: { foo: { otherField: string } } concrete: { foo: { otherField: "hello" } } }) #Container: { Env: { [string]: { name: string value: string } } } #Deployment: { #Containers: { [string]: 〈2;#Container〉 } containers: [ for _, c in 〈1;#Containers〉 { 〈1;c〉 }, ] } Something: { 〈1;#Deployment〉 #Containers: { "a thing": { Env: { foobar: { value: "foo" } } } } } x: (〈0;Something〉 & 〈0;#Deployment〉) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue320.txtar000066400000000000000000000034211474664451600240410ustar00rootroot00000000000000-- in.cue -- #Foo: { x: string #More } #More: [=~"^x-"]: _ foo: #Foo & { x: "hello" y: "goodbye" } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 4 Allocs: 3 Retain: 1 Unifications: 7 Conjuncts: 14 Disjuncts: 8 -- out/evalalpha -- Errors: foo.y: field not allowed: ./in.cue:6:19 ./in.cue:10:2 Result: (_|_){ // [eval] #Foo: (#struct){ x: (string){ string } } #More: (#struct){ } foo: (_|_){ // [eval] x: (string){ "hello" } y: (_|_){ // [eval] foo.y: field not allowed: // ./in.cue:6:19 // ./in.cue:10:2 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,6 @@ Errors: foo.y: field not allowed: - ./in.cue:1:7 - ./in.cue:3:2 - ./in.cue:6:8 - ./in.cue:8:6 + ./in.cue:6:19 ./in.cue:10:2 Result: @@ -19,10 +16,7 @@ x: (string){ "hello" } y: (_|_){ // [eval] foo.y: field not allowed: - // ./in.cue:1:7 - // ./in.cue:3:2 - // ./in.cue:6:8 - // ./in.cue:8:6 + // ./in.cue:6:19 // ./in.cue:10:2 } } -- diff/todo/p2 -- Positions. -- out/eval -- Errors: foo.y: field not allowed: ./in.cue:1:7 ./in.cue:3:2 ./in.cue:6:8 ./in.cue:8:6 ./in.cue:10:2 Result: (_|_){ // [eval] #Foo: (#struct){ x: (string){ string } } #More: (#struct){ } foo: (_|_){ // [eval] x: (string){ "hello" } y: (_|_){ // [eval] foo.y: field not allowed: // ./in.cue:1:7 // ./in.cue:3:2 // ./in.cue:6:8 // ./in.cue:8:6 // ./in.cue:10:2 } } } -- out/compile -- --- in.cue { #Foo: { x: string 〈1;#More〉 } #More: { [=~"^x-"]: _ } foo: (〈0;#Foo〉 & { x: "hello" y: "goodbye" }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue342.txtar000066400000000000000000000044641474664451600240550ustar00rootroot00000000000000-- in.cue -- X: { #Simple: { ref: string } #Complex: { { ref: string } | { local: string } } var: "XXX" // Validate(concrete) after Fill() on Complex.ref from a "static" key will succeed "test_1": #Complex // Validate(concrete) after Fill() on "#Simple.ref" from a "dynamic" key will succeed "test_2_\(var)": #Simple // Validate(concrete) after Fill() on Complex.ref from a "dynamic" key will fail "test_3_\(var)": #Complex test_3_XXX: ref: "FOO" } Z: X.test_3_XXX.ref -- out/eval/stats -- Leaks: 0 Freed: 24 Reused: 17 Allocs: 7 Retain: 2 Unifications: 18 Conjuncts: 33 Disjuncts: 24 -- out/evalalpha -- (struct){ X: (struct){ #Simple: (#struct){ ref: (string){ string } } #Complex: (#struct){ |((#struct){ ref: (string){ string } }, (#struct){ local: (string){ string } }) } var: (string){ "XXX" } test_1: (#struct){ |((#struct){ ref: (string){ string } }, (#struct){ local: (string){ string } }) } test_3_XXX: (#struct){ ref: (string){ "FOO" } } test_2_XXX: ~(X.#Simple) } Z: (string){ "FOO" } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -17,9 +17,7 @@ test_3_XXX: (#struct){ ref: (string){ "FOO" } } - test_2_XXX: (#struct){ - ref: (string){ string } - } + test_2_XXX: ~(X.#Simple) } Z: (string){ "FOO" } } -- out/eval -- (struct){ X: (struct){ #Simple: (#struct){ ref: (string){ string } } #Complex: (#struct){ |((#struct){ ref: (string){ string } }, (#struct){ local: (string){ string } }) } var: (string){ "XXX" } test_1: (#struct){ |((#struct){ ref: (string){ string } }, (#struct){ local: (string){ string } }) } test_3_XXX: (#struct){ ref: (string){ "FOO" } } test_2_XXX: (#struct){ ref: (string){ string } } } Z: (string){ "FOO" } } -- out/compile -- --- in.cue { X: { #Simple: { ref: string } #Complex: { ({ ref: string }|{ local: string }) } var: "XXX" test_1: 〈0;#Complex〉 "test_2_\(〈0;var〉)": 〈0;#Simple〉 "test_3_\(〈0;var〉)": 〈0;#Complex〉 test_3_XXX: { ref: "FOO" } } Z: 〈0;X〉.test_3_XXX.ref } cue-lang-cue-db9cc73/cue/testdata/definitions/issue359.txtar000066400000000000000000000053421474664451600240610ustar00rootroot00000000000000-- in.cue -- #simple: { peso: *1 | int edad: *2 | int } // Second struct is not considered closed, as expected good: #simple & { peso: 4 } #complex: { things: [string]: #simple } // Still, no closedness issue in the second struct #many: #complex & { things: hola: peso: 2 things: sol: peso: 3 } // Inner struct in second struct IS considered closed: why? bad: #many & { things: hola: peso: 2 } // non-definition equivalent many: #complex & { things: hola: peso: 2 things: sol: peso: 3 } // Now inner struct on second struct is NOT considered closed notbad: many & { things: hola: peso: 2 } -- out/eval/stats -- Leaks: 0 Freed: 81 Reused: 74 Allocs: 7 Retain: 0 Unifications: 41 Conjuncts: 134 Disjuncts: 81 -- out/eval -- (struct){ #simple: (#struct){ peso: (int){ |(*(int){ 1 }, (int){ int }) } edad: (int){ |(*(int){ 2 }, (int){ int }) } } good: (#struct){ peso: (int){ 4 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } #complex: (#struct){ things: (#struct){ } } #many: (#struct){ things: (#struct){ hola: (#struct){ peso: (int){ 2 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } sol: (#struct){ peso: (int){ 3 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } } } bad: (#struct){ things: (#struct){ hola: (#struct){ peso: (int){ 2 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } sol: (#struct){ peso: (int){ 3 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } } } many: (#struct){ things: (#struct){ hola: (#struct){ peso: (int){ 2 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } sol: (#struct){ peso: (int){ 3 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } } } notbad: (#struct){ things: (#struct){ hola: (#struct){ peso: (int){ 2 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } sol: (#struct){ peso: (int){ 3 } edad: (int){ |(*(int){ 2 }, (int){ int }) } } } } } -- out/compile -- --- in.cue { #simple: { peso: (*1|int) edad: (*2|int) } good: (〈0;#simple〉 & { peso: 4 }) #complex: { things: { [string]: 〈2;#simple〉 } } #many: (〈0;#complex〉 & { things: { hola: { peso: 2 } } things: { sol: { peso: 3 } } }) bad: (〈0;#many〉 & { things: { hola: { peso: 2 } } }) many: (〈0;#complex〉 & { things: { hola: { peso: 2 } } things: { sol: { peso: 3 } } }) notbad: (〈0;many〉 & { things: { hola: { peso: 2 } } }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue367.txtar000066400000000000000000000016421474664451600240570ustar00rootroot00000000000000TODO: l4 should be allowed -- in.cue -- #def1: l1: ["l2"]: {l3: int, l4: 26} #special1: #def1 & {l1: l2: l3: <100} instance: #special1 & {l1: l2: l3: 34} -- out/eval/stats -- Leaks: 0 Freed: 17 Reused: 12 Allocs: 5 Retain: 0 Unifications: 17 Conjuncts: 36 Disjuncts: 17 -- out/eval -- (struct){ #def1: (#struct){ l1: (#struct){ } } #special1: (#struct){ l1: (#struct){ l2: (#struct){ l3: (int){ &(<100, int) } l4: (int){ 26 } } } } instance: (#struct){ l1: (#struct){ l2: (#struct){ l3: (int){ 34 } l4: (int){ 26 } } } } } -- out/compile -- --- in.cue { #def1: { l1: { ["l2"]: { l3: int l4: 26 } } } #special1: (〈0;#def1〉 & { l1: { l2: { l3: <100 } } }) instance: (〈0;#special1〉 & { l1: { l2: { l3: 34 } } }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue370.txtar000066400000000000000000000026531474664451600240540ustar00rootroot00000000000000 -- x.cue -- package x #C1: { name: string } #C2: { #C1 age: int } c1: #C1 & { name: "cueckoo" } c2: #C2 & { c1 age: 5 } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 27 Disjuncts: 11 -- out/evalalpha -- (struct){ #C1: (#struct){ name: (string){ string } } #C2: (#struct){ age: (int){ int } name: (string){ string } } c1: (#struct){ name: (string){ "cueckoo" } } c2: (#struct){ age: (int){ 5 } name: (string){ "cueckoo" } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -3,14 +3,14 @@ name: (string){ string } } #C2: (#struct){ - name: (string){ string } age: (int){ int } + name: (string){ string } } c1: (#struct){ name: (string){ "cueckoo" } } c2: (#struct){ - name: (string){ "cueckoo" } age: (int){ 5 } + name: (string){ "cueckoo" } } } -- diff/explanation -- Reordering -- out/eval -- (struct){ #C1: (#struct){ name: (string){ string } } #C2: (#struct){ name: (string){ string } age: (int){ int } } c1: (#struct){ name: (string){ "cueckoo" } } c2: (#struct){ name: (string){ "cueckoo" } age: (int){ 5 } } } -- out/compile -- --- x.cue { #C1: { name: string } #C2: { 〈1;#C1〉 age: int } c1: (〈0;#C1〉 & { name: "cueckoo" }) c2: (〈0;#C2〉 & { 〈1;c1〉 age: 5 }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue419.txtar000066400000000000000000000013061474664451600240520ustar00rootroot00000000000000-- in.cue -- #A: { a: string } #B: { b: string } #X: #A | #B l: [...#X] l: [ {b: "bar"}, ] -- out/eval/stats -- Leaks: 0 Freed: 17 Reused: 12 Allocs: 5 Retain: 0 Unifications: 13 Conjuncts: 25 Disjuncts: 17 -- out/eval -- (struct){ #A: (#struct){ a: (string){ string } } #B: (#struct){ b: (string){ string } } #X: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ b: (string){ string } }) } l: (#list){ 0: (#struct){ b: (string){ "bar" } } } } -- out/compile -- --- in.cue { #A: { a: string } #B: { b: string } #X: (〈0;#A〉|〈0;#B〉) l: [ ...〈1;#X〉, ] l: [ { b: "bar" }, ] } cue-lang-cue-db9cc73/cue/testdata/definitions/issue471.txtar000066400000000000000000000021171474664451600240510ustar00rootroot00000000000000-- in.cue -- package x #a: (#c | #d) & { name: string } #a1: #c & { name: string } #a2: #d & { name: string } #c: { name: string age: int } #d: { name: string address: string } -- out/eval/stats -- Leaks: 0 Freed: 20 Reused: 14 Allocs: 6 Retain: 2 Unifications: 18 Conjuncts: 31 Disjuncts: 22 -- out/eval -- (struct){ #a: (#struct){ |((#struct){ name: (string){ string } age: (int){ int } }, (#struct){ name: (string){ string } address: (string){ string } }) } #a1: (#struct){ name: (string){ string } age: (int){ int } } #a2: (#struct){ name: (string){ string } address: (string){ string } } #c: (#struct){ name: (string){ string } age: (int){ int } } #d: (#struct){ name: (string){ string } address: (string){ string } } } -- out/compile -- --- in.cue { #a: ((〈0;#c〉|〈0;#d〉) & { name: string }) #a1: (〈0;#c〉 & { name: string }) #a2: (〈0;#d〉 & { name: string }) #c: { name: string age: int } #d: { name: string address: string } } cue-lang-cue-db9cc73/cue/testdata/definitions/issue483.txtar000066400000000000000000000017041474664451600240550ustar00rootroot00000000000000-- in.cue -- out: { instance } instance: #Type & { alpha: bravo: charlie: true } #Type: #Root & { alpha?: bravo?: charlie?: bool } #Root: {...} -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 7 Allocs: 7 Retain: 3 Unifications: 14 Conjuncts: 35 Disjuncts: 17 -- out/eval -- (struct){ out: (#struct){ alpha: (#struct){ bravo: (#struct){ charlie: (bool){ true } } } } instance: (#struct){ alpha: (#struct){ bravo: (#struct){ charlie: (bool){ true } } } } #Type: (#struct){ alpha?: (#struct){ bravo?: (#struct){ charlie?: (bool){ bool } } } } #Root: (#struct){ } } -- out/compile -- --- in.cue { out: { 〈1;instance〉 } instance: (〈0;#Type〉 & { alpha: { bravo: { charlie: true } } }) #Type: (〈0;#Root〉 & { alpha?: { bravo?: { charlie?: bool } } }) #Root: { ... } } cue-lang-cue-db9cc73/cue/testdata/definitions/issue491.txtar000066400000000000000000000034001474664451600240470ustar00rootroot00000000000000-- in.cue -- package x #Prestep: { Args: *null | _ } #PrestepNewUser: #Prestep & { Args: #NewUser } #NewUser: { Repos: [...#Repo] } #Repo: { Var: string Pattern: *"*" | string } x: [...#Repo] x: [{ Var: "REPO1" }] y: #Repo & { Var: "REPO1" } z: #PrestepNewUser & { Args: { Repos: [{ Var: "REPO1" }] } } -- out/eval/stats -- Leaks: 0 Freed: 45 Reused: 36 Allocs: 9 Retain: 1 Unifications: 29 Conjuncts: 71 Disjuncts: 46 -- out/eval -- (struct){ #Prestep: (#struct){ Args: (_){ |(*(null){ null }, (_){ _ }) } } #PrestepNewUser: (#struct){ Args: (#struct){ Repos: (list){ } } } #NewUser: (#struct){ Repos: (list){ } } #Repo: (#struct){ Var: (string){ string } Pattern: (string){ |(*(string){ "*" }, (string){ string }) } } x: (#list){ 0: (#struct){ Var: (string){ "REPO1" } Pattern: (string){ |(*(string){ "*" }, (string){ string }) } } } y: (#struct){ Var: (string){ "REPO1" } Pattern: (string){ |(*(string){ "*" }, (string){ string }) } } z: (#struct){ Args: (#struct){ Repos: (#list){ 0: (#struct){ Var: (string){ "REPO1" } Pattern: (string){ |(*(string){ "*" }, (string){ string }) } } } } } } -- out/compile -- --- in.cue { #Prestep: { Args: (*null|_) } #PrestepNewUser: (〈0;#Prestep〉 & { Args: 〈1;#NewUser〉 }) #NewUser: { Repos: [ ...〈2;#Repo〉, ] } #Repo: { Var: string Pattern: (*"*"|string) } x: [ ...〈1;#Repo〉, ] x: [ { Var: "REPO1" }, ] y: (〈0;#Repo〉 & { Var: "REPO1" }) z: (〈0;#PrestepNewUser〉 & { Args: { Repos: [ { Var: "REPO1" }, ] } }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue493.txtar000066400000000000000000000030221474664451600240510ustar00rootroot00000000000000-- in.cue -- #Artifact: { body: _ other: [string]: int } #App: #Artifact #Atom: #Artifact #Both: #App | #Atom t1: #Both & {body: 3} -- out/eval/stats -- Leaks: 0 Freed: 24 Reused: 19 Allocs: 5 Retain: 0 Unifications: 20 Conjuncts: 38 Disjuncts: 24 -- out/evalalpha -- (struct){ #Artifact: (#struct){ body: (_){ _ } other: (#struct){ } } #App: ~(#Artifact) #Atom: ~(#Artifact) #Both: (#struct){ body: (_){ _ } other: (#struct){ } } t1: (#struct){ body: (int){ 3 } other: (#struct){ } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,16 +4,8 @@ other: (#struct){ } } - #App: (#struct){ - body: (_){ _ } - other: (#struct){ - } - } - #Atom: (#struct){ - body: (_){ _ } - other: (#struct){ - } - } + #App: ~(#Artifact) + #Atom: ~(#Artifact) #Both: (#struct){ body: (_){ _ } other: (#struct){ -- out/eval -- (struct){ #Artifact: (#struct){ body: (_){ _ } other: (#struct){ } } #App: (#struct){ body: (_){ _ } other: (#struct){ } } #Atom: (#struct){ body: (_){ _ } other: (#struct){ } } #Both: (#struct){ body: (_){ _ } other: (#struct){ } } t1: (#struct){ body: (int){ 3 } other: (#struct){ } } } -- out/compile -- --- in.cue { #Artifact: { body: _ other: { [string]: int } } #App: 〈0;#Artifact〉 #Atom: 〈0;#Artifact〉 #Both: (〈0;#App〉|〈0;#Atom〉) t1: (〈0;#Both〉 & { body: 3 }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue496.txtar000066400000000000000000000015421474664451600240610ustar00rootroot00000000000000-- in.cue -- #A: _ #N: #A & { _E: { name: "hello" } } l: #N -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 4 Allocs: 4 Retain: 0 Unifications: 8 Conjuncts: 13 Disjuncts: 8 -- out/evalalpha -- (struct){ #A: (_){ _ } #N: (#struct){ _E: (#struct){ name: (string){ "hello" } } } l: ~(#N) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -5,9 +5,5 @@ name: (string){ "hello" } } } - l: (#struct){ - _E: (#struct){ - name: (string){ "hello" } - } - } + l: ~(#N) } -- out/eval -- (struct){ #A: (_){ _ } #N: (#struct){ _E: (#struct){ name: (string){ "hello" } } } l: (#struct){ _E: (#struct){ name: (string){ "hello" } } } } -- out/compile -- --- in.cue { #A: _ #N: (〈0;#A〉 & { _E: { name: "hello" } }) l: 〈0;#N〉 } cue-lang-cue-db9cc73/cue/testdata/definitions/issue497.txtar000066400000000000000000000016661474664451600240710ustar00rootroot00000000000000-- in.cue -- #A: _ #N: #A & { f: j: { n: "hi" } } l: #N -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 5 Allocs: 5 Retain: 0 Unifications: 10 Conjuncts: 15 Disjuncts: 10 -- out/evalalpha -- (struct){ #A: (_){ _ } #N: (#struct){ f: (#struct){ j: (#struct){ n: (string){ "hi" } } } } l: ~(#N) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -7,11 +7,5 @@ } } } - l: (#struct){ - f: (#struct){ - j: (#struct){ - n: (string){ "hi" } - } - } - } + l: ~(#N) } -- out/eval -- (struct){ #A: (_){ _ } #N: (#struct){ f: (#struct){ j: (#struct){ n: (string){ "hi" } } } } l: (#struct){ f: (#struct){ j: (#struct){ n: (string){ "hi" } } } } } -- out/compile -- --- in.cue { #A: _ #N: (〈0;#A〉 & { f: { j: { n: "hi" } } }) l: 〈0;#N〉 } cue-lang-cue-db9cc73/cue/testdata/definitions/issue533.txtar000066400000000000000000000047711474664451600240600ustar00rootroot00000000000000-- in.cue -- package x #x: { Name: string } _#x: { Name: string } x1: #x & { Name: "hello" Age: 50 } x2: _#x & { Name: "hello" Age: 50 } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 17 Disjuncts: 11 -- out/evalalpha -- Errors: x1.Age: field not allowed: ./in.cue:11:5 ./in.cue:13:2 x2.Age: field not allowed: ./in.cue:16:5 ./in.cue:18:2 Result: (_|_){ // [eval] #x: (#struct){ Name: (string){ string } } _#x(:x): (#struct){ Name: (string){ string } } x1: (_|_){ // [eval] Name: (string){ "hello" } Age: (_|_){ // [eval] x1.Age: field not allowed: // ./in.cue:11:5 // ./in.cue:13:2 } } x2: (_|_){ // [eval] Name: (string){ "hello" } Age: (_|_){ // [eval] x2.Age: field not allowed: // ./in.cue:16:5 // ./in.cue:18:2 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,10 +1,8 @@ Errors: x1.Age: field not allowed: - ./in.cue:3:5 ./in.cue:11:5 ./in.cue:13:2 x2.Age: field not allowed: - ./in.cue:7:6 ./in.cue:16:5 ./in.cue:18:2 @@ -22,7 +20,6 @@ Name: (string){ "hello" } Age: (_|_){ // [eval] x1.Age: field not allowed: - // ./in.cue:3:5 // ./in.cue:11:5 // ./in.cue:13:2 } @@ -32,7 +29,6 @@ Name: (string){ "hello" } Age: (_|_){ // [eval] x2.Age: field not allowed: - // ./in.cue:7:6 // ./in.cue:16:5 // ./in.cue:18:2 } -- diff/todo/p2 -- Positions. -- out/eval -- Errors: x1.Age: field not allowed: ./in.cue:3:5 ./in.cue:11:5 ./in.cue:13:2 x2.Age: field not allowed: ./in.cue:7:6 ./in.cue:16:5 ./in.cue:18:2 Result: (_|_){ // [eval] #x: (#struct){ Name: (string){ string } } _#x(:x): (#struct){ Name: (string){ string } } x1: (_|_){ // [eval] Name: (string){ "hello" } Age: (_|_){ // [eval] x1.Age: field not allowed: // ./in.cue:3:5 // ./in.cue:11:5 // ./in.cue:13:2 } } x2: (_|_){ // [eval] Name: (string){ "hello" } Age: (_|_){ // [eval] x2.Age: field not allowed: // ./in.cue:7:6 // ./in.cue:16:5 // ./in.cue:18:2 } } } -- out/compile -- --- in.cue { #x: { Name: string } _#x: { Name: string } x1: (〈0;#x〉 & { Name: "hello" Age: 50 }) x2: (〈0;_#x〉 & { Name: "hello" Age: 50 }) } cue-lang-cue-db9cc73/cue/testdata/definitions/issue539.txtar000066400000000000000000000015051474664451600240560ustar00rootroot00000000000000-- in.cue -- #Schema: { ... } Component: { hostname: string | *"localhost" _#foo: { hello: "world" } } hello: #Schema & Component -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 9 Allocs: 5 Retain: 0 Unifications: 10 Conjuncts: 18 Disjuncts: 14 -- out/eval -- (struct){ #Schema: (#struct){ } Component: (struct){ hostname: (string){ |(*(string){ "localhost" }, (string){ string }) } _#foo: (#struct){ hello: (string){ "world" } } } hello: (#struct){ hostname: (string){ |(*(string){ "localhost" }, (string){ string }) } _#foo: (#struct){ hello: (string){ "world" } } } } -- out/compile -- --- in.cue { #Schema: { ... } Component: { hostname: (string|*"localhost") _#foo: { hello: "world" } } hello: (〈0;#Schema〉 & 〈0;Component〉) } cue-lang-cue-db9cc73/cue/testdata/definitions/list.txtar000066400000000000000000000020741474664451600234420ustar00rootroot00000000000000-- in.cue -- c: #R & { w: [{}, {b: int}] } #R: { w: [{}, ...] } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 4 Allocs: 5 Retain: 1 Unifications: 9 Conjuncts: 14 Disjuncts: 10 -- out/evalalpha -- (struct){ c: (#struct){ w: (#list){ 0: (#struct){ } 1: (#struct){ b: (int){ int } } } } #R: (#struct){ w: (list){ 0: (#struct){ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -3,7 +3,7 @@ w: (#list){ 0: (#struct){ } - 1: (struct){ + 1: (#struct){ b: (int){ int } } } -- diff/explanation -- Bug fix. Struct is correctly closed in new evaluator. -- out/eval -- (struct){ c: (#struct){ w: (#list){ 0: (#struct){ } 1: (struct){ b: (int){ int } } } } #R: (#struct){ w: (list){ 0: (#struct){ } } } } -- out/compile -- --- in.cue { c: (〈0;#R〉 & { w: [ {}, { b: int }, ] }) #R: { w: [ {}, ..., ] } } cue-lang-cue-db9cc73/cue/testdata/definitions/visibility.txtar000066400000000000000000000023621474664451600246560ustar00rootroot00000000000000-- in.cue -- #foo: { name: string } foo: #foo & { // These should all be allowed. _name: "foo" _#name: "bar" #name: "baz" } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 5 Allocs: 3 Retain: 0 Unifications: 8 Conjuncts: 10 Disjuncts: 8 -- out/evalalpha -- (struct){ #foo: (#struct){ name: (string){ string } } foo: (#struct){ _name: (string){ "foo" } _#name: (string){ "bar" } #name: (string){ "baz" } name: (string){ string } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -3,9 +3,9 @@ name: (string){ string } } foo: (#struct){ - name: (string){ string } _name: (string){ "foo" } _#name: (string){ "bar" } #name: (string){ "baz" } + name: (string){ string } } } -- diff/todo/p3 -- Reordering. -- diff/explanation -- New evaluator should ultimately disallow new definitions in closed structs. -- out/eval -- (struct){ #foo: (#struct){ name: (string){ string } } foo: (#struct){ name: (string){ string } _name: (string){ "foo" } _#name: (string){ "bar" } #name: (string){ "baz" } } } -- out/compile -- --- in.cue { #foo: { name: string } foo: (〈0;#foo〉 & { _name: "foo" _#name: "bar" #name: "baz" }) } cue-lang-cue-db9cc73/cue/testdata/disjunctions/000077500000000000000000000000001474664451600216015ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/disjunctions/019_ips.txtar000066400000000000000000000042271474664451600240560ustar00rootroot00000000000000#name: ips #evalFull -- in.cue -- import "list" IP: list.Repeat([uint8], 4) Private: *[ 192, 168, uint8, uint8] | [ 10, uint8, uint8, uint8] | [ 172, >=16 & <=32, uint8, uint8] Inst: Private & [ _, 10, ...] MyIP: Inst & [_, _, 10, 10] -- out/def -- IP: [uint8, uint8, uint8, uint8] Private: *[192, 168, uint8, uint8] | [10, uint8, uint8, uint8] | [172, >=16 & <=32, uint8, uint8] Inst: [10, 10, uint8, uint8] MyIP: [10, 10, 10, 10] -- out/legacy-debug -- <0>{IP: [(int & >=0 & int & <=255),(int & >=0 & int & <=255),(int & >=0 & int & <=255),(int & >=0 & int & <=255)], Private: [192,168,(int & >=0 & int & <=255),(int & >=0 & int & <=255)], Inst: [10,10,(int & >=0 & int & <=255),(int & >=0 & int & <=255)], MyIP: [10,10,10,10]} -- out/compile -- --- in.cue { IP: 〈import;list〉.Repeat([ &(int, >=0, <=255), ], 4) Private: (*[ 192, 168, &(int, >=0, <=255), &(int, >=0, <=255), ]|[ 10, &(int, >=0, <=255), &(int, >=0, <=255), &(int, >=0, <=255), ]|[ 172, (>=16 & <=32), &(int, >=0, <=255), &(int, >=0, <=255), ]) Inst: (〈0;Private〉 & [ _, 10, ..., ]) MyIP: (〈0;Inst〉 & [ _, _, 10, 10, ]) } -- out/eval/stats -- Leaks: 0 Freed: 56 Reused: 50 Allocs: 6 Retain: 1 Unifications: 47 Conjuncts: 106 Disjuncts: 57 -- out/eval -- (struct){ IP: (#list){ 0: (int){ &(>=0, <=255, int) } 1: (int){ &(>=0, <=255, int) } 2: (int){ &(>=0, <=255, int) } 3: (int){ &(>=0, <=255, int) } } Private: (list){ |(*(#list){ 0: (int){ 192 } 1: (int){ 168 } 2: (int){ &(>=0, <=255, int) } 3: (int){ &(>=0, <=255, int) } }, (#list){ 0: (int){ 10 } 1: (int){ &(>=0, <=255, int) } 2: (int){ &(>=0, <=255, int) } 3: (int){ &(>=0, <=255, int) } }, (#list){ 0: (int){ 172 } 1: (number){ &(>=16, <=32) } 2: (int){ &(>=0, <=255, int) } 3: (int){ &(>=0, <=255, int) } }) } Inst: (#list){ 0: (int){ 10 } 1: (int){ 10 } 2: (int){ &(>=0, <=255, int) } 3: (int){ &(>=0, <=255, int) } } MyIP: (#list){ 0: (int){ 10 } 1: (int){ 10 } 2: (int){ 10 } 3: (int){ 10 } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/defembed.txtar000066400000000000000000000115771474664451600244330ustar00rootroot00000000000000Interaction between defaults, embedding and disjunctions. // TODO: at the moment, using a default will select it. -- in.cue -- x: { // All of these resolve to *2 | 3 m1: (1 | (*2 | 3)) & (>=2 & <=3) m2: (1 | (*2 | 3)) & (2 | 3) m3: (*1 | *(*2 | 3)) & (2 | 3) } y1: x & { {m4: x.m1 + x.m2 + x.m3} } y2: { x {m4: y2.m1 + y2.m2 + y2.m3} } Y=y3: { x {m4: Y.m1 + Y.m2 + Y.m3} } y4: x & { {m4: y4.m1 + y4.m2 + y4.m3} } // Second disjunct in embedding is not possible because of previous declaration // of `b`, so it should be resolved to {a: 1}. z: { b: (*"a" | "b") | "c" {a: b} | {b: int} } -- out/eval/stats -- Leaks: 0 Freed: 163 Reused: 155 Allocs: 8 Retain: 0 Unifications: 29 Conjuncts: 198 Disjuncts: 163 -- out/eval -- (struct){ x: (struct){ m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y1: (struct){ m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } m4: (int){ 6 } } y2: (struct){ m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } m4: (int){ 6 } } y3: (struct){ m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } m4: (int){ 6 } } y4: (struct){ m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } m4: (int){ 6 } } z: (struct){ b: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } a: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } } -- out/evalalpha -- (struct){ x: (struct){ m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y1: (struct){ m4: (int){ 6 } m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y2: (struct){ m4: (int){ 6 } m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y3: (struct){ m4: (int){ 6 } m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y4: (struct){ m4: (int){ 6 } m1: (int){ |(*(int){ 2 }, (int){ 3 }) } m2: (int){ |(*(int){ 2 }, (int){ 3 }) } m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } z: (struct){ b: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } a: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -5,28 +5,28 @@ m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y1: (struct){ - m1: (int){ |(*(int){ 2 }, (int){ 3 }) } - m2: (int){ |(*(int){ 2 }, (int){ 3 }) } - m3: (int){ |(*(int){ 2 }, (int){ 3 }) } - m4: (int){ 6 } + m4: (int){ 6 } + m1: (int){ |(*(int){ 2 }, (int){ 3 }) } + m2: (int){ |(*(int){ 2 }, (int){ 3 }) } + m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y2: (struct){ - m1: (int){ |(*(int){ 2 }, (int){ 3 }) } - m2: (int){ |(*(int){ 2 }, (int){ 3 }) } - m3: (int){ |(*(int){ 2 }, (int){ 3 }) } - m4: (int){ 6 } + m4: (int){ 6 } + m1: (int){ |(*(int){ 2 }, (int){ 3 }) } + m2: (int){ |(*(int){ 2 }, (int){ 3 }) } + m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y3: (struct){ - m1: (int){ |(*(int){ 2 }, (int){ 3 }) } - m2: (int){ |(*(int){ 2 }, (int){ 3 }) } - m3: (int){ |(*(int){ 2 }, (int){ 3 }) } - m4: (int){ 6 } + m4: (int){ 6 } + m1: (int){ |(*(int){ 2 }, (int){ 3 }) } + m2: (int){ |(*(int){ 2 }, (int){ 3 }) } + m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } y4: (struct){ - m1: (int){ |(*(int){ 2 }, (int){ 3 }) } - m2: (int){ |(*(int){ 2 }, (int){ 3 }) } - m3: (int){ |(*(int){ 2 }, (int){ 3 }) } - m4: (int){ 6 } + m4: (int){ 6 } + m1: (int){ |(*(int){ 2 }, (int){ 3 }) } + m2: (int){ |(*(int){ 2 }, (int){ 3 }) } + m3: (int){ |(*(int){ 2 }, (int){ 3 }) } } z: (struct){ b: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } -- diff/todo/p3 -- Reordering. -- out/compile -- --- in.cue { x: { m1: ((1|(*2|3)) & (>=2 & <=3)) m2: ((1|(*2|3)) & (2|3)) m3: ((*1|*(*2|3)) & (2|3)) } y1: (〈0;x〉 & { { m4: ((〈2;x〉.m1 + 〈2;x〉.m2) + 〈2;x〉.m3) } }) y2: { 〈1;x〉 { m4: ((〈2;y2〉.m1 + 〈2;y2〉.m2) + 〈2;y2〉.m3) } } y3: { 〈1;x〉 { m4: ((〈2;y3〉.m1 + 〈2;y3〉.m2) + 〈2;y3〉.m3) } } y4: (〈0;x〉 & { { m4: ((〈2;y4〉.m1 + 〈2;y4〉.m2) + 〈2;y4〉.m3) } }) z: { b: ((*"a"|"b")|"c") ({ a: 〈1;b〉 }|{ b: int }) } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/edge.txtar000066400000000000000000000203571474664451600236000ustar00rootroot00000000000000# This file mostly contains edge cases of disjunction semantics. # We should ensure that all these cases can be derived from thee spec. # # Many of these cases were discovered as part of the development of the new # evaluator that started at v0.7 and do not pass for that version. -- in.cue -- cyclicalInsertInDisjunction: { // We do not allow lookups across unresolved disjunctions. As such, the // references across disjunctions are not allowed to disambiguate a // disjunction. // // Algorithmically, the distinction between allowing this or not is // achieved by allowing dereferencing of the node in which a disjunction // occurs to the disjunct under evaluation. Effectively this is what the // v0.6 evaluator does. ok1: { // In this case, unifying the comprehension into the processing of the // disjunctions would _not_ case the reference to cross disjunction // boundaries. c: {d: e, e: _} c: {d: 1, e: 2} | {d : 2, e: 2} } maybe1: { // In this case, the reference c.e crosses a disjunction boundary. // However, since the reference starts from within a disjunction, this // could be allowed, if we define it to be. c: d: c.e c: {d: 1, e: 2} | {d : 2, e: 2} } err1: { // This should be an error: to resolve x in c.d, we need to first // resolve x to a concrete value. As `x` is defined outside the // disjunction, and the disjunction cannot be resolved without it, `x` // cannot be evaluated to a concrete value, resulting in an error. x: c.e c: d: x c: {d: 1, e: 2} | {d : 2, e: 2} } err2: { // This is a more obviously erroneous variant of err1. The div in x // requires a concrete value for c.e. However, the disjunction can only // be disambiguated as a result of computing x. This means c.e cannot // be concrete at the time of evaluation. x: div(c.e, 2) c: d: x c: {d: 1, e: 2} | {d : 2, e: 3} } err3: { // Here it is clear that d will not disambiguate the disjunction at c. // So c.e. cannot be resolved. x: c.e c: d: 1 | 2 | x c: {d: 1, e: 2} | {d : 2, e: 3} } } preseveBottomSemantics: ok: { // `a: a`, which just says that `a` is `a`, is logically equivalent to // `a: _`. Consequently, the disjunction `a: a | X` is equivalent to // `a: _ | X`. As we do not simplify disjunctions, the result is `a: _ | X`. // However, we could consider simplifying in this case to `a: _` if we can // come up with a good general mechanism for subsumption. #x: { #x | {} } } eliminateOpenVariant: ok: { // We have two structs in the disjunction that are identical in every way // except openness. TODO: should we disambiguate those? c: {a: 1} | #b #b: {a: 1} } cyclicSelfElimination: ok: { // This should resolve to {y: 1} (works for new evaluator) y: 1 | {y: 1} y } -- out/eval/stats -- Leaks: 0 Freed: 73 Reused: 62 Allocs: 11 Retain: 11 Unifications: 49 Conjuncts: 105 Disjuncts: 74 -- out/eval -- (struct){ cyclicalInsertInDisjunction: (struct){ ok1: (struct){ c: (struct){ d: (int){ 2 } e: (int){ 2 } } } maybe1: (struct){ c: (struct){ d: (int){ 2 } e: (int){ 2 } } } err1: (struct){ x: (int){ 2 } c: (struct){ d: (int){ 2 } e: (int){ 2 } } } err2: (struct){ x: (int){ 1 } c: (struct){ d: (int){ 1 } e: (int){ 2 } } } err3: (struct){ x: (_|_){ // [incomplete] cyclicalInsertInDisjunction.err3.x: unresolved disjunction {d:1,e:2} | {d:2,e:3} (type struct): // ./in.cue:46:6 } c: (struct){ |((struct){ d: (int){ 1 } e: (int){ 2 } }, (struct){ d: (int){ 2 } e: (int){ 3 } }) } } } preseveBottomSemantics: (struct){ ok: (struct){ #x: (#struct){ } } } eliminateOpenVariant: (struct){ ok: (struct){ c: (#struct){ |((struct){ a: (int){ 1 } }, (#struct){ a: (int){ 1 } }) } #b: (#struct){ a: (int){ 1 } } } } cyclicSelfElimination: (struct){ ok: (_|_){ // [incomplete] cyclicSelfElimination.ok: 2 errors in empty disjunction: // cyclicSelfElimination.ok: conflicting values 1 and {y:(1|{y:1}),y} (mismatched types int and struct): // ./in.cue:68:28 // ./in.cue:70:5 // cyclicSelfElimination.ok: cannot add field y: was already used: // ./in.cue:70:10 y: ((int|struct)){ |((int){ 1 }, (struct){ y: (int){ 1 } }) } } } } -- out/evalalpha -- (struct){ cyclicalInsertInDisjunction: (struct){ ok1: (struct){ c: (struct){ d: (int){ 2 } e: (int){ 2 } } } maybe1: (struct){ c: (struct){ d: (int){ 2 } e: (int){ 2 } } } err1: (struct){ x: (int){ 2 } c: (struct){ d: (int){ 2 } e: (int){ 2 } } } err2: (struct){ x: (int){ 1 } c: (struct){ d: (int){ 1 } e: (int){ 2 } } } err3: (struct){ x: (_|_){ // [incomplete] cyclicalInsertInDisjunction.err3.x: unresolved disjunction {d:1,e:2} | {d:2,e:3} (type struct): // ./in.cue:46:6 } c: (struct){ |((struct){ d: (int){ 1 } e: (int){ 2 } }, (struct){ d: (int){ 2 } e: (int){ 3 } }) } } } preseveBottomSemantics: (struct){ ok: (struct){ #x: (#struct){ } } } eliminateOpenVariant: (struct){ ok: (struct){ c: (struct){ |((struct){ a: (int){ 1 } }, (#struct){ a: (int){ 1 } }) } #b: (#struct){ a: (int){ 1 } } } } cyclicSelfElimination: (struct){ ok: (struct){ y: (int){ 1 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -48,7 +48,7 @@ } eliminateOpenVariant: (struct){ ok: (struct){ - c: (#struct){ |((struct){ + c: (struct){ |((struct){ a: (int){ 1 } }, (#struct){ a: (int){ 1 } @@ -59,16 +59,8 @@ } } cyclicSelfElimination: (struct){ - ok: (_|_){ - // [incomplete] cyclicSelfElimination.ok: 2 errors in empty disjunction: - // cyclicSelfElimination.ok: conflicting values 1 and {y:(1|{y:1}),y} (mismatched types int and struct): - // ./in.cue:68:28 - // ./in.cue:70:5 - // cyclicSelfElimination.ok: cannot add field y: was already used: - // ./in.cue:70:10 - y: ((int|struct)){ |((int){ 1 }, (struct){ - y: (int){ 1 } - }) } + ok: (struct){ + y: (int){ 1 } } } } -- diff/todo/p2 -- cyclicalInsertInDisjunction.maybe: discrepancy may be okay cyclicalInsertInDisjunction.err1: should be an err for the old and new evaluator. -- diff/todo/p3 -- preseveBottomSemantics: both the old and new evaluator are incorrect here. The result should be either _ or _|{}. -- diff/explanation -- cyclicalInsertInDisjunction.err2: The new evaluator handles this correctly. eliminateOpenVariant.ok: closedness of c is different. Seems correct, or at least okay. cyclicSelfElimination.ok: The new evaluator handles this correctly. -- out/compile -- --- in.cue { cyclicalInsertInDisjunction: { ok1: { c: { d: 〈0;e〉 e: _ } c: ({ d: 1 e: 2 }|{ d: 2 e: 2 }) } maybe1: { c: { d: 〈1;c〉.e } c: ({ d: 1 e: 2 }|{ d: 2 e: 2 }) } err1: { x: 〈0;c〉.e c: { d: 〈1;x〉 } c: ({ d: 1 e: 2 }|{ d: 2 e: 2 }) } err2: { x: div(〈0;c〉.e, 2) c: { d: 〈1;x〉 } c: ({ d: 1 e: 2 }|{ d: 2 e: 3 }) } err3: { x: 〈0;c〉.e c: { d: (1|2|〈1;x〉) } c: ({ d: 1 e: 2 }|{ d: 2 e: 3 }) } } preseveBottomSemantics: { ok: { #x: { (〈1;#x〉|{}) } } } eliminateOpenVariant: { ok: { c: ({ a: 1 }|〈0;#b〉) #b: { a: 1 } } } cyclicSelfElimination: { ok: { y: (1|{ y: 1 }) 〈0;y〉 } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/elimination.txtar000066400000000000000000003501401474664451600252000ustar00rootroot00000000000000// Ensure that disjunction elimination is not done prematurely. // Issue #651 -- in.cue -- import "struct" // Closedness checks should not be triggered too early, or with an improper // subset of StructInfos. Blindly finalizing partial disjuncts will end up // doing a closedness check with not all embeddings present, which can lead to // a field being rejected prematurely. // // It should be recursively disabled. disambiguateClosed: { b: #Def & a a: #Def #Def: {{x: true} | {y: true}} } // Checks should never be disabled for field matching. alwaysCheckMatchers1: { b: {[=~"^xxxx$"]: int} | null b: {c: string} | null b: c: "yyyyy" } alwaysCheckPatterns2: { a: #X a: b b: #X b: c: "yyyyy" #X: string | { c: string {[=~"^xxxx$"]: int} } } nestedNonMonotonic: resolved: n1: { x: {a: struct.MinFields(2)} | null x: {a: c: 1} | null x: {a: d: 1} | null } nestedNonMonotonic: resolved: n2: { x: {a: b: struct.MinFields(2)} | null x: {a: b: c: 1} | null x: {a: b: d: 1} | null } nestedNonMonotonic: eliminated: n1: p1: { x: {a: struct.MaxFields(1)} | null x: {a: c: 1} | null x: {a: d: 1} | null } nestedNonMonotonic: eliminated: n1: p2: { x: {a: c: 1} | null x: {a: struct.MaxFields(1)} | null x: {a: d: 1} | null } nestedNonMonotonic: eliminated: n1: p2: { x: {a: c: 1} | null x: {a: d: 1} | null x: {a: struct.MaxFields(1)} | null } nestedNonMonotonic: eliminated: n2: p1: { x: {a: b: struct.MaxFields(1)} | null x: {a: b: c: 1} | null x: {a: b: d: 1} | null } nestedNonMonotonic: eliminated: n2: p2: { x: {a: b: c: 1} | null x: {a: b: struct.MaxFields(1)} | null x: {a: b: d: 1} | null } nestedNonMonotonic: eliminated: n2: p2: { x: {a: b: c: 1} | null x: {a: b: d: 1} | null x: {a: b: struct.MaxFields(1)} | null } // TODO: should be incomplete. nestedNonMonotonic: incomplete: a: n1: p1: { x: {a: struct.MinFields(2)} | null x: {a: c: 1} | null } // TODO: should be incomplete. nestedNonMonotonic: incomplete: a: n1: p2: { x: {a: c: 1} | null x: {a: struct.MinFields(2)} | null } nestedNonMonotonic: incomplete: a: n2: p1: { x: {a: b: struct.MinFields(2)} | null x: {a: b: c: 1} | null } nestedNonMonotonic: incomplete: a: n2: p2: { x: {a: b: c: 1} | null x: {a: b: struct.MinFields(2)} | null } nestedNonMonotonic: incomplete: b: n1: p1: { x: {a: struct.MinFields(3)} | null x: {a: c: 1} | null x: {a: d: 1} | null } nestedNonMonotonic: incomplete: b: n1: p2: { x: {a: c: 1} | null x: {a: struct.MinFields(3)} | null x: {a: d: 1} | null } nestedNonMonotonic: incomplete: b: n1: p3: { x: {a: c: 1} | null x: {a: d: 1} | null x: {a: struct.MinFields(3)} | null } nestedNonMonotonic: incomplete: b: n2: p1: { x: {a: b: struct.MinFields(3)} | null x: {a: b: c: 1} | null x: {a: b: d: 1} | null } nestedNonMonotonic: incomplete: b: n2: p1: { x: {a: b: c: 1} | null x: {a: b: struct.MinFields(3)} | null x: {a: b: d: 1} | null } nestedNonMonotonic: incomplete: b: n2: p1: { x: {a: b: c: 1} | null x: {a: b: d: 1} | null x: {a: b: struct.MinFields(3)} | null } preserveClosedness: small: p1: { #A: #B & {a: string} #B: { *{} | {a: string} *{} | {b: int} } } preserveClosedness: small: p2: { #A: #B & {a: string} #B: { {a: string} | *{} *{} | {b: int} } } preserveClosedness: medium: p1: { #A: #B & {a: string} #B: { *{} | {a: string} | {b: string} *{} | {c: int} | {d: string} } } preserveClosedness: medium: p2: { #A: #B & {a: string} #B: { {a: string} | *{} | {b: string} *{} | {c: int} | {d: string} } } preserveClosedness: medium: p3: { #A: #B & {a: string} #B: { {a: string} | {b: string} | *{} *{} | {c: int} | {d: string} } } // If an error occurred in the last disjunction, it may sometimes be propagated // to parent nodes. This, in turn, could lead to references to such field // to fail with that error. noChildError: _ noChildError: issue1608: { myValue: #type & {fieldName: "some string"} #type: fieldName: #subtype #subtype: string | {foo: string} | {bar: #subtype} } noChildError: t1: { #D: {b: string} | {c: #D } o: #D & {b: "test"} } noChildError: t2: { o: #D & {b: "test"} #D: {b: string} | {c: #D } } noChildError: t3: { #D: {a: null} | {b: string} | {c: #D } o: #D & {b: "test"} } noChildError: t4: { o: #D & {b: "test"} #D: {a: null} | {b: string} | {c: #D } } issue1924: t1: { m: a: 2 x: *[m.b] | 2 } issue1924: t2: { m: a: 2 x: *{v: m.b} | 3 } issue1924: t3: { m: a: 2 x: *m.b | 1 } // should eliminate erroneous comprehension and pass issue1838: t1: { p?: [] a: [for k in p {k}] | null } issue1838: t2: { p?: [] a: null | [for k in p {k}] } noHang: { // This should terminate. #T: ["a", #T] | ["d", ...#T] x: #T #X: x #X: #T } issue1940: { #T: ["a", #T] | ["b", #T] | ["c", #T] | ["d", [...#T]] #A: type: #T #B: [string]: #A #C: #B & { x: #A } } -- issue2209full.cue -- // TODO: fix issue2209: simplified: t1: { #SpecFoo: foo: min: 1 #SpecBar: bar: min: 1 spec: bar: {} spec: #SpecFoo | #SpecBar out: { {nullFoo: null} | {nullBar: null} {minFoo: int} | {minBar: int} if X.bar != _|_ { minBar: X.bar.min } X: spec } } issue2209: simplified: t2: { #SpecFoo: foo: {} #SpecBar: bar: x: 1 spec: bar: {} spec: *#SpecFoo | #SpecBar if spec.bar != _|_ { BAZ: spec.bar.x } {f1: int} | {b2: int} {f2: int} | {b2: int} } // This test fails for 0.4 and 0.5. issue2209: simplified: t3: { #A: v: 1 {f1: int} | {b2: int} {f2: int} | {b2: int} BAZ: S.y S: *#A | #B #B: {x: 1, y: 1} S: x: 1 } issue2209: full: { Foo: #Abstract & {spec: foo: {}} Bar: #Abstract & {spec: bar: {}} #Abstract: X={ spec: _#Spec resource: _Thing & {_X: spec: X.spec} } _#Spec: *_#SpecFoo | _#SpecBar _#SpecFoo: { foo: { min: int | *10 max: int | *20 } } _#SpecBar: { bar: { min: int | *30 max: int | *40 } } _Thing: #Constrained & { _X: _ spec: { if _X.spec.foo != _|_ { minFoo: _X.spec.foo.min maxFoo: _X.spec.foo.max } if _X.spec.bar != _|_ { minBar: _X.spec.bar.min maxBar: _X.spec.bar.max } } } #Constrained: #Base & { spec: { minFoo: int | *10 maxFoo: int | *20 minBar?: null maxBar?: null } | { minBar: int | *30 maxBar: int | *40 minFoo?: null maxFoo?: null } spec: *{ fuga?: null } | { hoge?: null } } #Base: { spec: { minFoo?: null | int maxFoo?: null | int minBar?: null | int maxBar?: null | int hoge?: null | bool fuga?: null | bool } } } -- issue2246.cue -- issue2246: simplified: { #FormFoo: fooID: string #FormBar: barID: string #Form: { #FormFoo | #FormBar } data: {fooID: "123"} out1: #Form & data out2: #Form & out1 } issue2246: full: { data: forms: [{ fooID: "00-0000001" }] form1040: (#compute & {in: data}).out #K1: { #_base: common: 3 #FormFoo: { #_base fooID: string } #FormBar: { #_base barID: string } #Form: { #FormFoo | #FormBar } } #Input: { forms: [...#K1.#Form] } #summarizeReturn: { in: #Input out: [for k in in.forms { k.common }] } #compute: { in: #Input out: (#summarizeReturn & {"in": in}).out } } -- issue2263.cue -- issue2263: simplified: { metrics: #Metric #Metric: { #IDSource | {} #TargetAverage | {} } metrics: { id: "foo" avg: 60 } #IDSource: id: string #TargetAverage: avg: number } issue2263: full: { metrics: [...#Metric] metrics: [{ id: "foo" avg: 60 }, { id: "bar" value: 80 }, { uri: "baz" avg: 70 }, { uri: "qux" value: 90 }] #Metric: { #Source #Target } #Source: #IDSource | #URISource #Target: #TargetAverage | #TargetValue #IDSource: { id: string } #URISource: { uri: string } #TargetAverage: { avg: number } #TargetValue: { value: number } } -- issue1417.cue -- issue1417: { #ID: !~"^a" | =~"^ab$" | =~"^aB$" #ID: =~"^a" | !~"[A-Z]" ids: [...#ID] & ["xyz", "ab", "aB"] } -- issue3149.cue -- issue3149: { #valid: { name!: ( (=~"^Foo") | "an exception") & ( (=~"Foo$") | "an exception") } list: [...#valid] list: [ {name: "FooBarFoo"}, {name: "FooBazFoo"}, {name: "FooQuuxFoo"}, {name: "an exception"}, ] } -- issue770.cue -- issue770: { #A: { v: "a" | "b" | "c" } h: [string]: #A h: a: { v: *"a" | string } h: [=~"^b"]: { v: *h.a.v | string } h: [=~"^c"]: { v: *h.b.v | string } h: b: _ h: boo: _ h: c: _ h: coo: _ } -- issue3528.cue -- issue3528: original: { workflows: [...#Workflow] workflows: [test] test: #Workflow & {} #Workflow: { container: [string]: string | #container #container: string | {volumes?: [...string]} } } issue3528: reduced: { a?: #A a: #A & {} #A: { A: [string]: 1 | #a #a: 2 | {v: 1} } } issue3528: counter: { } issue3528: nested: t1: { {v: 1} | (2 | 3) {v: 1} | (2 | 3) {v: 1} | (2 | 3) {v: 1} | (2 | 3) } issue3528: nested: t2: { {v: 1} | 2 {v: 1} | (2 | 3) {v: 1} | 2 {v: 1} | 2 } -- out/evalalpha -- (struct){ disambiguateClosed: (struct){ b: (#struct){ |((#struct){ x: (bool){ true } }, (#struct){ y: (bool){ true } }) } a: (#struct){ |((#struct){ x: (bool){ true } }, (#struct){ y: (bool){ true } }) } #Def: (#struct){ |((#struct){ x: (bool){ true } }, (#struct){ y: (bool){ true } }) } } alwaysCheckMatchers1: (struct){ b: (struct){ c: (string){ "yyyyy" } } } alwaysCheckPatterns2: (struct){ a: (#struct){ c: (string){ "yyyyy" } } b: (#struct){ c: (string){ "yyyyy" } } #X: ((string|struct)){ |((string){ string }, (#struct){ c: (string){ string } }) } } nestedNonMonotonic: (struct){ resolved: (struct){ n1: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ c: (int){ 1 } d: (int){ 1 } } }, (null){ null }) } } n2: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (struct){ c: (int){ 1 } d: (int){ 1 } } } }, (null){ null }) } } } eliminated: (struct){ n1: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } } n2: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } } } incomplete: (struct){ a: (struct){ n1: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } } n2: (struct){ p1: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ // [incomplete] nestedNonMonotonic.incomplete.a.n2.p1.x.a.b: invalid value {c:1} (does not satisfy struct.MinFields(2)): len(fields) < MinFields(2) (1 < 2): // ./in.cue:96:15 // ./in.cue:96:32 // ./in.cue:97:12 c: (int){ 1 } } } }, (null){ null }) } } p2: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ // [incomplete] nestedNonMonotonic.incomplete.a.n2.p2.x.a.b: invalid value {c:1} (does not satisfy struct.MinFields(2)): len(fields) < MinFields(2) (1 < 2): // ./in.cue:102:15 // ./in.cue:101:12 // ./in.cue:102:32 c: (int){ 1 } } } }, (null){ null }) } } } } b: (struct){ n1: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } p3: (struct){ x: (null){ null } } } n2: (struct){ p1: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ // [incomplete] nestedNonMonotonic.incomplete.b.n2.p1.x.a.b: invalid value {c:1,d:1} (does not satisfy struct.MinFields(3)): len(fields) < MinFields(3) (2 < 3): // ./in.cue:138:15 // ./in.cue:124:15 // ./in.cue:125:12 // ./in.cue:126:12 // ./in.cue:130:12 // ./in.cue:131:15 // ./in.cue:132:12 // ./in.cue:136:12 // ./in.cue:137:12 // ./in.cue:138:32 c: (int){ 1 } d: (int){ 1 } } } }, (null){ null }) } } } } } } preserveClosedness: (struct){ small: (struct){ p1: (struct){ #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } b: (int){ int } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ b: (int){ int } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } b: (int){ int } }) } } p2: (struct){ #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } b: (int){ int } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ a: (string){ string } b: (int){ int } }, (#struct){ a: (string){ string } }, (#struct){ b: (int){ int } }) } } } medium: (struct){ p1: (struct){ #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ c: (int){ int } }, (#struct){ d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (int){ int } }, (#struct){ b: (string){ string } d: (string){ string } }) } } p2: (struct){ #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ c: (int){ int } }, (#struct){ d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (int){ int } }, (#struct){ b: (string){ string } d: (string){ string } }) } } p3: (struct){ #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (int){ int } }, (#struct){ b: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ c: (int){ int } }, (#struct){ d: (string){ string } }) } } } } noChildError: (struct){ issue1608: (struct){ myValue: (#struct){ fieldName: (string){ "some string" } } #type: (#struct){ fieldName: ((string|struct)){ |((string){ string }, (#struct){ foo: (string){ string } }) } } #subtype: ((string|struct)){ |((string){ string }, (#struct){ foo: (string){ string } }) } } t1: (struct){ #D: (#struct){ b: (string){ string } } o: (#struct){ b: (string){ "test" } } } t2: (struct){ o: (#struct){ b: (string){ "test" } } #D: (#struct){ b: (string){ string } } } t3: (struct){ #D: (#struct){ |((#struct){ a: (null){ null } }, (#struct){ b: (string){ string } }) } o: (#struct){ b: (string){ "test" } } } t4: (struct){ o: (#struct){ b: (string){ "test" } } #D: (#struct){ |((#struct){ a: (null){ null } }, (#struct){ b: (string){ string } }) } } } issue1924: (struct){ t1: (struct){ m: (struct){ a: (int){ 2 } } x: (int){ 2 } } t2: (struct){ m: (struct){ a: (int){ 2 } } x: (int){ 3 } } t3: (struct){ m: (struct){ a: (int){ 2 } } x: (int){ 1 } } } issue1838: (struct){ t1: (struct){ p?: (#list){ } a: (null){ null } } t2: (struct){ p?: (#list){ } a: (null){ null } } } noHang: (struct){ #T: (list){ 0: (string){ "d" } } x: ~(noHang.#T) #X: ~(noHang.#T) } issue1940: (struct){ #T: (#list){ 0: (string){ "d" } 1: (list){ } } #A: (#struct){ type: ~(issue1940.#T) } #B: (#struct){ } #C: (#struct){ x: ~(issue1940.#A) } } issue1417: (struct){ #ID: (string){ |((string){ &(!~"^a", =~"^a") }, (string){ &(!~"^a", !~"[A-Z]") }, (string){ &(=~"^ab$", =~"^a") }, (string){ &(=~"^ab$", !~"[A-Z]") }, (string){ &(=~"^aB$", =~"^a") }, (string){ &(=~"^aB$", !~"[A-Z]") }) } ids: (#list){ 0: (string){ "xyz" } 1: (string){ "ab" } 2: (string){ "aB" } } } issue2209: (struct){ simplified: (struct){ t1: (struct){ #SpecFoo: (#struct){ foo: (#struct){ min: (int){ 1 } } } #SpecBar: (#struct){ bar: (#struct){ min: (int){ 1 } } } spec: (#struct){ bar: (#struct){ min: (int){ 1 } } } out: (struct){ |((struct){ X: ~(issue2209.simplified.t1.spec) nullFoo: (null){ null } minFoo: (int){ int } }, (struct){ minBar: (int){ int } X: ~(issue2209.simplified.t1.spec) nullFoo: (null){ null } }, (struct){ X: ~(issue2209.simplified.t1.spec) nullBar: (null){ null } minFoo: (int){ int } }, (struct){ minBar: (int){ int } X: ~(issue2209.simplified.t1.spec) nullBar: (null){ null } }) } } t2: (_|_){ // [incomplete] issue2209.simplified.t2.BAZ: undefined field: x: // ./issue2209full.cue:24:17 #SpecFoo: (#struct){ foo: (#struct){ } } #SpecBar: (#struct){ bar: (#struct){ x: (int){ 1 } } } spec: (struct){ bar: (struct){ } } BAZ: (_){ _ } } t3: (struct){ |((struct){ #A: (#struct){ v: (int){ 1 } } BAZ: (_){ _ } S: (#struct){ x: (int){ 1 } y: (int){ 1 } } #B: (#struct){ x: (int){ 1 } y: (int){ 1 } } f1: (int){ int } f2: (int){ int } }, (struct){ #A: (#struct){ v: (int){ 1 } } BAZ: (_){ _ } S: (#struct){ x: (int){ 1 } y: (int){ 1 } } #B: (#struct){ x: (int){ 1 } y: (int){ 1 } } f1: (int){ int } b2: (int){ int } }) } } full: (struct){ Foo: (#struct){ spec: (#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } } resource: (#struct){ _X: (#struct){ spec: ~(issue2209.full.Foo.spec) } spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } } } Bar: (#struct){ spec: (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } } resource: (#struct){ _X: (#struct){ spec: ~(issue2209.full.Bar.spec) } spec: (#struct){ |(*(#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } } } #Abstract: (#struct){ spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } resource: (#struct){ _X: (#struct){ spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } } spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } } } _#Spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } _#SpecFoo: (#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } } _#SpecBar: (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } } _Thing: (#struct){ _X: (_){ _ } spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, *(#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }, (#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } } #Constrained: (#struct){ spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, *(#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }, (#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } } #Base: (#struct){ spec: (#struct){ minFoo?: ((null|int)){ |((null){ null }, (int){ int }) } maxFoo?: ((null|int)){ |((null){ null }, (int){ int }) } minBar?: ((null|int)){ |((null){ null }, (int){ int }) } maxBar?: ((null|int)){ |((null){ null }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } } } } } issue2246: (struct){ simplified: (struct){ #FormFoo: (#struct){ fooID: (string){ string } } #FormBar: (#struct){ barID: (string){ string } } #Form: (#struct){ |((#struct){ fooID: (string){ string } }, (#struct){ barID: (string){ string } }) } data: (struct){ fooID: (string){ "123" } } out1: (#struct){ fooID: (string){ "123" } } out2: (#struct){ fooID: (string){ "123" } } } full: (struct){ data: (struct){ forms: (#list){ 0: (struct){ fooID: (string){ "00-0000001" } } } } form1040: (#list){ 0: (int){ 3 } } #K1: (#struct){ #_base: (#struct){ common: (int){ 3 } } #FormFoo: (#struct){ fooID: (string){ string } common: (int){ 3 } } #FormBar: (#struct){ barID: (string){ string } common: (int){ 3 } } #Form: (#struct){ |((#struct){ fooID: (string){ string } common: (int){ 3 } }, (#struct){ barID: (string){ string } common: (int){ 3 } }) } } #Input: (#struct){ forms: (list){ } } #summarizeReturn: (#struct){ in: ~(issue2246.full.#Input) out: (#list){ } } #compute: (#struct){ in: ~(issue2246.full.#Input) out: (#list){ } } } } issue2263: (struct){ simplified: (struct){ metrics: (#struct){ id: (string){ "foo" } avg: (int){ 60 } } #Metric: (#struct){ |((#struct){ id: (string){ string } avg: (number){ number } }, (#struct){ id: (string){ string } }, (#struct){ avg: (number){ number } }, (#struct){ }) } #IDSource: (#struct){ id: (string){ string } } #TargetAverage: (#struct){ avg: (number){ number } } } full: (struct){ metrics: (#list){ 0: (#struct){ |((#struct){ id: (string){ "foo" } avg: (int){ 60 } }, (#struct){ id: (string){ "foo" } avg: (int){ 60 } value: (number){ number } }, (#struct){ id: (string){ "foo" } avg: (int){ 60 } uri: (string){ string } }, (#struct){ id: (string){ "foo" } avg: (int){ 60 } uri: (string){ string } value: (number){ number } }) } 1: (#struct){ id: (string){ "bar" } value: (int){ 80 } } 2: (#struct){ uri: (string){ "baz" } avg: (int){ 70 } } 3: (#struct){ uri: (string){ "qux" } value: (int){ 90 } } } #Metric: (#struct){ |((#struct){ id: (string){ string } avg: (number){ number } }, (#struct){ id: (string){ string } value: (number){ number } }, (#struct){ uri: (string){ string } avg: (number){ number } }, (#struct){ uri: (string){ string } value: (number){ number } }) } #Source: (#struct){ |((#struct){ id: (string){ string } }, (#struct){ uri: (string){ string } }) } #Target: (#struct){ |((#struct){ avg: (number){ number } }, (#struct){ value: (number){ number } }) } #IDSource: (#struct){ id: (string){ string } } #URISource: (#struct){ uri: (string){ string } } #TargetAverage: (#struct){ avg: (number){ number } } #TargetValue: (#struct){ value: (number){ number } } } } issue3149: (struct){ #valid: (#struct){ name!: (string){ |((string){ &(=~"^Foo", =~"Foo$") }, (string){ "an exception" }) } } list: (#list){ 0: (#struct){ name: (string){ "FooBarFoo" } } 1: (#struct){ name: (string){ "FooBazFoo" } } 2: (#struct){ name: (string){ "FooQuuxFoo" } } 3: (#struct){ name: (string){ "an exception" } } } } issue3528: (struct){ original: (struct){ workflows: (#list){ 0: (#struct){ container: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ volumes?: (list){ } }) } } } test: (#struct){ container: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ volumes?: (list){ } }) } } #Workflow: (#struct){ container: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ volumes?: (list){ } }) } } } reduced: (struct){ a: (#struct){ A: (#struct){ } #a: ((int|struct)){ |((int){ 2 }, (#struct){ v: (int){ 1 } }) } } #A: (#struct){ A: (#struct){ } #a: ((int|struct)){ |((int){ 2 }, (#struct){ v: (int){ 1 } }) } } } counter: (struct){ } nested: (struct){ t1: ((int|struct)){ |((struct){ v: (int){ 1 } }, (int){ 2 }, (int){ 3 }) } t2: ((int|struct)){ |((struct){ v: (int){ 1 } }, (int){ 2 }) } } } issue770: (struct){ #A: (#struct){ v: (string){ |((string){ "a" }, (string){ "b" }, (string){ "c" }) } } h: (struct){ a: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } b: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } boo: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } c: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } coo: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,58 +1,4 @@ -Errors: -issue1417.ids.2: 2 errors in empty disjunction: -issue2209.full.Bar.resource.spec: 6 errors in empty disjunction: -issue2209.full.Bar.resource.spec.minBar: 2 errors in empty disjunction: -issue2209.full.Bar.resource.spec.minBar: conflicting values null and int (mismatched types null and int): - ./issue2209full.cue:43:7 - ./issue2209full.cue:48:13 - ./issue2209full.cue:67:10 - ./issue2209full.cue:83:16 - ./issue2209full.cue:87:13 - ./issue2209full.cue:107:20 -issue2209.full.Bar.resource.spec.minFoo: 2 errors in empty disjunction: -issue2209.full.Bar.resource.spec.minFoo: conflicting values null and 10 (mismatched types null and int): - ./issue2209full.cue:43:7 - ./issue2209full.cue:48:13 - ./issue2209full.cue:55:16 - ./issue2209full.cue:71:4 - ./issue2209full.cue:72:13 - ./issue2209full.cue:92:13 -issue2209.full.Bar.resource.spec.minFoo: conflicting values null and int (mismatched types null and int): - ./issue2209full.cue:43:7 - ./issue2209full.cue:48:13 - ./issue2209full.cue:67:10 - ./issue2209full.cue:83:16 - ./issue2209full.cue:92:13 - ./issue2209full.cue:105:20 -issue3149.list.3.name: 2 errors in empty disjunction: -issue1417.ids.1: invalid value "ab" (out of bound !~"^a"): - ./issue1417.cue:2:7 - ./issue1417.cue:4:11 - ./issue1417.cue:4:26 -issue1417.ids.2: invalid value "aB" (out of bound !~"^a"): - ./issue1417.cue:2:7 - ./issue1417.cue:4:11 - ./issue1417.cue:4:32 -issue1417.ids.2: invalid value "aB" (out of bound !~"[A-Z]"): - ./issue1417.cue:3:16 - ./issue1417.cue:4:11 - ./issue1417.cue:4:32 -issue2209.simplified.t3.BAZ: undefined field: y: - ./issue2209full.cue:35:9 -issue2209.full.Bar.resource.spec.minBar: undefined field: min: - ./issue2209full.cue:77:25 -issue3149.list.3.name: invalid value "an exception" (out of bound =~"^Foo"): - ./issue3149.cue:3:13 - ./issue3149.cue:3:10 - ./issue3149.cue:10:10 -issue3149.list.3.name: invalid value "an exception" (out of bound =~"Foo$"): - ./issue3149.cue:3:46 - ./issue3149.cue:3:10 - ./issue3149.cue:10:10 - -Result: -(_|_){ - // [eval] +(struct){ disambiguateClosed: (struct){ b: (#struct){ |((#struct){ x: (bool){ true } @@ -181,7 +127,7 @@ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ - // [incomplete] nestedNonMonotonic.incomplete.b.n2.p1.x.a.b: invalid value {c:1 & 1 & 1,d:1 & 1 & 1} (does not satisfy struct.MinFields(3)): len(fields) < MinFields(3) (2 < 3): + // [incomplete] nestedNonMonotonic.incomplete.b.n2.p1.x.a.b: invalid value {c:1,d:1} (does not satisfy struct.MinFields(3)): len(fields) < MinFields(3) (2 < 3): // ./in.cue:138:15 // ./in.cue:124:15 // ./in.cue:125:12 @@ -205,24 +151,24 @@ preserveClosedness: (struct){ small: (struct){ p1: (struct){ - #A: (#struct){ |(*(#struct){ - a: (string){ string } - }, (#struct){ - a: (string){ string } - b: (int){ int } - }) } - #B: (#struct){ |(*(#struct){ - }, (#struct){ - b: (int){ int } - }, (#struct){ - a: (string){ string } - }, (#struct){ - a: (string){ string } - b: (int){ int } - }) } - } - p2: (struct){ - #A: (#struct){ |(*(#struct){ + #A: (#struct){ |((#struct){ + a: (string){ string } + }, (#struct){ + a: (string){ string } + b: (int){ int } + }) } + #B: (#struct){ |(*(#struct){ + }, (#struct){ + b: (int){ int } + }, (#struct){ + a: (string){ string } + }, (#struct){ + a: (string){ string } + b: (int){ int } + }) } + } + p2: (struct){ + #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } @@ -241,40 +187,40 @@ } medium: (struct){ p1: (struct){ - #A: (#struct){ |(*(#struct){ - a: (string){ string } - }, (#struct){ - a: (string){ string } - c: (int){ int } - }, (#struct){ - a: (string){ string } - d: (string){ string } - }) } - #B: (#struct){ |(*(#struct){ - }, (#struct){ - c: (int){ int } - }, (#struct){ - d: (string){ string } - }, (#struct){ - a: (string){ string } - }, (#struct){ - a: (string){ string } - c: (int){ int } - }, (#struct){ - a: (string){ string } - d: (string){ string } - }, (#struct){ - b: (string){ string } - }, (#struct){ - b: (string){ string } - c: (int){ int } - }, (#struct){ - b: (string){ string } - d: (string){ string } - }) } - } - p2: (struct){ - #A: (#struct){ |(*(#struct){ + #A: (#struct){ |((#struct){ + a: (string){ string } + }, (#struct){ + a: (string){ string } + c: (int){ int } + }, (#struct){ + a: (string){ string } + d: (string){ string } + }) } + #B: (#struct){ |(*(#struct){ + }, (#struct){ + c: (int){ int } + }, (#struct){ + d: (string){ string } + }, (#struct){ + a: (string){ string } + }, (#struct){ + a: (string){ string } + c: (int){ int } + }, (#struct){ + a: (string){ string } + d: (string){ string } + }, (#struct){ + b: (string){ string } + }, (#struct){ + b: (string){ string } + c: (int){ int } + }, (#struct){ + b: (string){ string } + d: (string){ string } + }) } + } + p2: (struct){ + #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } @@ -307,7 +253,7 @@ }) } } p3: (struct){ - #A: (#struct){ |(*(#struct){ + #A: (#struct){ |((#struct){ a: (string){ string } }, (#struct){ a: (string){ string } @@ -349,10 +295,6 @@ #type: (#struct){ fieldName: ((string|struct)){ |((string){ string }, (#struct){ foo: (string){ string } - }, (#struct){ - bar: ((string|struct)){ |((string){ string }, (#struct){ - foo: (string){ string } - }) } }) } } #subtype: ((string|struct)){ |((string){ string }, (#struct){ @@ -432,12 +374,8 @@ #T: (list){ 0: (string){ "d" } } - x: (list){ - 0: (string){ "d" } - } - #X: (list){ - 0: (string){ "d" } - } + x: ~(noHang.#T) + #X: ~(noHang.#T) } issue1940: (struct){ #T: (#list){ @@ -446,53 +384,24 @@ } } #A: (#struct){ - type: (#list){ - 0: (string){ "d" } - 1: (list){ - } - } + type: ~(issue1940.#T) } #B: (#struct){ } #C: (#struct){ - x: (#struct){ - type: (#list){ - 0: (string){ "d" } - 1: (list){ - } - } - } - } - } - issue1417: (_|_){ - // [eval] + x: ~(issue1940.#A) + } + } + issue1417: (struct){ #ID: (string){ |((string){ &(!~"^a", =~"^a") }, (string){ &(!~"^a", !~"[A-Z]") }, (string){ &(=~"^ab$", =~"^a") }, (string){ &(=~"^ab$", !~"[A-Z]") }, (string){ &(=~"^aB$", =~"^a") }, (string){ &(=~"^aB$", !~"[A-Z]") }) } - ids: (_|_){ - // [eval] + ids: (#list){ 0: (string){ "xyz" } - 1: (_|_){ - // [eval] issue1417.ids.1: invalid value "ab" (out of bound !~"^a"): - // ./issue1417.cue:2:7 - // ./issue1417.cue:4:11 - // ./issue1417.cue:4:26 - } - 2: (_|_){ - // [eval] issue1417.ids.2: 2 errors in empty disjunction: - // issue1417.ids.2: invalid value "aB" (out of bound !~"^a"): - // ./issue1417.cue:2:7 - // ./issue1417.cue:4:11 - // ./issue1417.cue:4:32 - // issue1417.ids.2: invalid value "aB" (out of bound !~"[A-Z]"): - // ./issue1417.cue:3:16 - // ./issue1417.cue:4:11 - // ./issue1417.cue:4:32 - } - } - } - issue2209: (_|_){ - // [eval] - simplified: (_|_){ - // [eval] + 1: (string){ "ab" } + 2: (string){ "aB" } + } + } + issue2209: (struct){ + simplified: (struct){ t1: (struct){ #SpecFoo: (#struct){ foo: (#struct){ @@ -510,36 +419,20 @@ } } out: (struct){ |((struct){ - X: (#struct){ - bar: (#struct){ - min: (int){ 1 } - } - } - nullFoo: (null){ null } - minFoo: (int){ int } - }, (struct){ - minBar: (int){ int } - X: (#struct){ - bar: (#struct){ - min: (int){ 1 } - } - } - nullFoo: (null){ null } - }, (struct){ - X: (#struct){ - bar: (#struct){ - min: (int){ 1 } - } - } - nullBar: (null){ null } - minFoo: (int){ int } - }, (struct){ - minBar: (int){ int } - X: (#struct){ - bar: (#struct){ - min: (int){ 1 } - } - } + X: ~(issue2209.simplified.t1.spec) + nullFoo: (null){ null } + minFoo: (int){ int } + }, (struct){ + minBar: (int){ int } + X: ~(issue2209.simplified.t1.spec) + nullFoo: (null){ null } + }, (struct){ + X: ~(issue2209.simplified.t1.spec) + nullBar: (null){ null } + minFoo: (int){ int } + }, (struct){ + minBar: (int){ int } + X: ~(issue2209.simplified.t1.spec) nullBar: (null){ null } }) } } @@ -555,48 +448,45 @@ x: (int){ 1 } } } - spec: (#struct){ |(*(#struct){ - bar: (struct){ - } - foo: (#struct){ - } - }, (#struct){ - bar: (#struct){ - x: (int){ 1 } - } - }) } - BAZ: (_|_){ - // [incomplete] issue2209.simplified.t2.BAZ: undefined field: x: - // ./issue2209full.cue:24:17 - } - b2: (int){ int } - } - t3: (_|_){ - // [eval] issue2209.simplified.t3.BAZ: undefined field: y: - // ./issue2209full.cue:35:9 - #A: (#struct){ - v: (int){ 1 } - } - BAZ: (_|_){ - // [eval] issue2209.simplified.t3.BAZ: undefined field: y: - // ./issue2209full.cue:35:9 - } - S: (#struct){ |(*(#struct){ - x: (int){ 1 } - v: (int){ 1 } - }, (#struct){ - x: (int){ 1 } - y: (int){ 1 } - }) } - #B: (#struct){ - x: (int){ 1 } - y: (int){ 1 } - } - b2: (int){ int } - } - } - full: (_|_){ - // [eval] + spec: (struct){ + bar: (struct){ + } + } + BAZ: (_){ _ } + } + t3: (struct){ |((struct){ + #A: (#struct){ + v: (int){ 1 } + } + BAZ: (_){ _ } + S: (#struct){ + x: (int){ 1 } + y: (int){ 1 } + } + #B: (#struct){ + x: (int){ 1 } + y: (int){ 1 } + } + f1: (int){ int } + f2: (int){ int } + }, (struct){ + #A: (#struct){ + v: (int){ 1 } + } + BAZ: (_){ _ } + S: (#struct){ + x: (int){ 1 } + y: (int){ 1 } + } + #B: (#struct){ + x: (int){ 1 } + y: (int){ 1 } + } + f1: (int){ int } + b2: (int){ int } + }) } + } + full: (struct){ Foo: (#struct){ spec: (#struct){ foo: (#struct){ @@ -605,135 +495,52 @@ } } resource: (#struct){ - spec: (#struct){ |(*(#struct){ - minFoo: (int){ |(*(int){ 10 }, (int){ int }) } - maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } - minBar?: (null){ null } - maxBar?: (null){ null } - hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - fuga?: (null){ null } - }, (#struct){ - minFoo: (int){ |(*(int){ 10 }, (int){ int }) } - maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } - minBar?: (null){ null } - maxBar?: (null){ null } - hoge?: (null){ null } - fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - }) } - _X: (#struct){ - spec: (#struct){ |(*(#struct){ - foo: (#struct){ - min: (int){ |(*(int){ 10 }, (int){ int }) } - max: (int){ |(*(int){ 20 }, (int){ int }) } - } - }, (#struct){ - foo: (#struct){ - } - bar: (#struct){ - min: (int){ |(*(int){ 30 }, (int){ int }) } - max: (int){ |(*(int){ 40 }, (int){ int }) } - } - }) } - } - } - } - Bar: (_|_){ - // [eval] - spec: (#struct){ - bar: (#struct){ - min: (int){ |(*(int){ 30 }, (int){ int }) } - max: (int){ |(*(int){ 40 }, (int){ int }) } - } - } - resource: (_|_){ - // [eval] - spec: (_|_){ - // [eval] issue2209.full.Bar.resource.spec: 6 errors in empty disjunction: - // issue2209.full.Bar.resource.spec.minBar: 2 errors in empty disjunction: - // issue2209.full.Bar.resource.spec.minBar: conflicting values null and int (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:67:10 - // ./issue2209full.cue:83:16 - // ./issue2209full.cue:87:13 - // ./issue2209full.cue:107:20 - // issue2209.full.Bar.resource.spec.minFoo: 2 errors in empty disjunction: - // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and 10 (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:55:16 - // ./issue2209full.cue:71:4 - // ./issue2209full.cue:72:13 - // ./issue2209full.cue:92:13 - // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and int (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:67:10 - // ./issue2209full.cue:83:16 - // ./issue2209full.cue:92:13 - // ./issue2209full.cue:105:20 - // issue2209.full.Bar.resource.spec.minBar: undefined field: min: - // ./issue2209full.cue:77:25 - minFoo: (_|_){ - // [eval] issue2209.full.Bar.resource.spec.minFoo: 2 errors in empty disjunction: - // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and 10 (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:55:16 - // ./issue2209full.cue:71:4 - // ./issue2209full.cue:72:13 - // ./issue2209full.cue:92:13 - // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and int (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:67:10 - // ./issue2209full.cue:83:16 - // ./issue2209full.cue:92:13 - // ./issue2209full.cue:105:20 - } - maxFoo: (_|_){ - // [eval] issue2209.full.Bar.resource.spec.maxFoo: 2 errors in empty disjunction: - // issue2209.full.Bar.resource.spec.maxFoo: conflicting values null and 20 (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:56:16 - // ./issue2209full.cue:71:4 - // ./issue2209full.cue:73:13 - // ./issue2209full.cue:93:13 - // issue2209.full.Bar.resource.spec.maxFoo: conflicting values null and int (mismatched types null and int): - // ./issue2209full.cue:43:7 - // ./issue2209full.cue:48:13 - // ./issue2209full.cue:67:10 - // ./issue2209full.cue:83:16 - // ./issue2209full.cue:93:13 - // ./issue2209full.cue:106:20 - } - minBar: (_|_){ - // [eval] issue2209.full.Bar.resource.spec.minBar: undefined field: min: - // ./issue2209full.cue:77:25 - } - maxBar: (_|_){ - // [eval] issue2209.full.Bar.resource.spec.maxBar: undefined field: max: - // ./issue2209full.cue:78:25 - } - hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - } - _X: (#struct){ - spec: (#struct){ |(*(#struct){ - bar: (#struct){ - } - foo: (#struct){ - min: (int){ |(*(int){ 10 }, (int){ int }) } - max: (int){ |(*(int){ 20 }, (int){ int }) } - } - }, (#struct){ - bar: (#struct){ - min: (int){ |(*(int){ 30 }, (int){ int }) } - max: (int){ |(*(int){ 40 }, (int){ int }) } - } - }) } - } + _X: (#struct){ + spec: ~(issue2209.full.Foo.spec) + } + spec: (#struct){ |(*(#struct){ + minFoo: (int){ |(*(int){ 10 }, (int){ int }) } + maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } + minBar?: (null){ null } + maxBar?: (null){ null } + hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + fuga?: (null){ null } + }, (#struct){ + minFoo: (int){ |(*(int){ 10 }, (int){ int }) } + maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } + minBar?: (null){ null } + maxBar?: (null){ null } + hoge?: (null){ null } + fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + }) } + } + } + Bar: (#struct){ + spec: (#struct){ + bar: (#struct){ + min: (int){ |(*(int){ 30 }, (int){ int }) } + max: (int){ |(*(int){ 40 }, (int){ int }) } + } + } + resource: (#struct){ + _X: (#struct){ + spec: ~(issue2209.full.Bar.spec) + } + spec: (#struct){ |(*(#struct){ + minFoo?: (null){ null } + maxFoo?: (null){ null } + minBar: (int){ |(*(int){ 30 }, (int){ int }) } + maxBar: (int){ |(*(int){ 40 }, (int){ int }) } + hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + fuga?: (null){ null } + }, (#struct){ + minFoo?: (null){ null } + maxFoo?: (null){ null } + minBar: (int){ |(*(int){ 30 }, (int){ int }) } + maxBar: (int){ |(*(int){ 40 }, (int){ int }) } + hoge?: (null){ null } + fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + }) } } } #Abstract: (#struct){ @@ -749,34 +556,34 @@ } }) } resource: (#struct){ - spec: (#struct){ |(*(#struct){ - minFoo: (int){ |(*(int){ 10 }, (int){ int }) } - maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } - minBar?: (null){ null } - maxBar?: (null){ null } - hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - fuga?: (null){ null } - }, (#struct){ - minFoo: (int){ |(*(int){ 10 }, (int){ int }) } - maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } - minBar?: (null){ null } - maxBar?: (null){ null } - hoge?: (null){ null } - fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - }) } - _X: (#struct){ - spec: (#struct){ |(*(#struct){ - foo: (#struct){ - min: (int){ |(*(int){ 10 }, (int){ int }) } - max: (int){ |(*(int){ 20 }, (int){ int }) } - } - }, (#struct){ - bar: (#struct){ - min: (int){ |(*(int){ 30 }, (int){ int }) } - max: (int){ |(*(int){ 40 }, (int){ int }) } - } - }) } - } + _X: (#struct){ + spec: (#struct){ |(*(#struct){ + foo: (#struct){ + min: (int){ |(*(int){ 10 }, (int){ int }) } + max: (int){ |(*(int){ 20 }, (int){ int }) } + } + }, (#struct){ + bar: (#struct){ + min: (int){ |(*(int){ 30 }, (int){ int }) } + max: (int){ |(*(int){ 40 }, (int){ int }) } + } + }) } + } + spec: (#struct){ |(*(#struct){ + minFoo: (int){ |(*(int){ 10 }, (int){ int }) } + maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } + minBar?: (null){ null } + maxBar?: (null){ null } + hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + fuga?: (null){ null } + }, (#struct){ + minFoo: (int){ |(*(int){ 10 }, (int){ int }) } + maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } + minBar?: (null){ null } + maxBar?: (null){ null } + hoge?: (null){ null } + fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + }) } } } _#Spec: (#struct){ |(*(#struct){ @@ -803,36 +610,36 @@ } } _Thing: (#struct){ - spec: (#struct){ |(*(#struct){ - minFoo: (int){ |(*(int){ 10 }, (int){ int }) } - maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } - minBar?: (null){ null } - maxBar?: (null){ null } - hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - fuga?: (null){ null } - }, *(#struct){ - minFoo?: (null){ null } - maxFoo?: (null){ null } - minBar: (int){ |(*(int){ 30 }, (int){ int }) } - maxBar: (int){ |(*(int){ 40 }, (int){ int }) } - hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - fuga?: (null){ null } - }, (#struct){ - minFoo: (int){ |(*(int){ 10 }, (int){ int }) } - maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } - minBar?: (null){ null } - maxBar?: (null){ null } - hoge?: (null){ null } - fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - }, (#struct){ - minFoo?: (null){ null } - maxFoo?: (null){ null } - minBar: (int){ |(*(int){ 30 }, (int){ int }) } - maxBar: (int){ |(*(int){ 40 }, (int){ int }) } - hoge?: (null){ null } - fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } - }) } _X: (_){ _ } + spec: (#struct){ |(*(#struct){ + minFoo: (int){ |(*(int){ 10 }, (int){ int }) } + maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } + minBar?: (null){ null } + maxBar?: (null){ null } + hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + fuga?: (null){ null } + }, *(#struct){ + minFoo?: (null){ null } + maxFoo?: (null){ null } + minBar: (int){ |(*(int){ 30 }, (int){ int }) } + maxBar: (int){ |(*(int){ 40 }, (int){ int }) } + hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + fuga?: (null){ null } + }, (#struct){ + minFoo: (int){ |(*(int){ 10 }, (int){ int }) } + maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } + minBar?: (null){ null } + maxBar?: (null){ null } + hoge?: (null){ null } + fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + }, (#struct){ + minFoo?: (null){ null } + maxFoo?: (null){ null } + minBar: (int){ |(*(int){ 30 }, (int){ int }) } + maxBar: (int){ |(*(int){ 40 }, (int){ int }) } + hoge?: (null){ null } + fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } + }) } } #Constrained: (#struct){ spec: (#struct){ |(*(#struct){ @@ -916,19 +723,19 @@ common: (int){ 3 } } #FormFoo: (#struct){ - common: (int){ 3 } - fooID: (string){ string } + fooID: (string){ string } + common: (int){ 3 } } #FormBar: (#struct){ - common: (int){ 3 } - barID: (string){ string } + barID: (string){ string } + common: (int){ 3 } } #Form: (#struct){ |((#struct){ - common: (int){ 3 } fooID: (string){ string } - }, (#struct){ - common: (int){ 3 } + common: (int){ 3 } + }, (#struct){ barID: (string){ string } + common: (int){ 3 } }) } } #Input: (#struct){ @@ -936,18 +743,12 @@ } } #summarizeReturn: (#struct){ - in: (#struct){ - forms: (list){ - } - } + in: ~(issue2246.full.#Input) out: (#list){ } } #compute: (#struct){ - in: (#struct){ - forms: (list){ - } - } + in: ~(issue2246.full.#Input) out: (#list){ } } @@ -977,10 +778,23 @@ } full: (struct){ metrics: (#list){ - 0: (#struct){ - id: (string){ "foo" } - avg: (int){ 60 } - } + 0: (#struct){ |((#struct){ + id: (string){ "foo" } + avg: (int){ 60 } + }, (#struct){ + id: (string){ "foo" } + avg: (int){ 60 } + value: (number){ number } + }, (#struct){ + id: (string){ "foo" } + avg: (int){ 60 } + uri: (string){ string } + }, (#struct){ + id: (string){ "foo" } + avg: (int){ 60 } + uri: (string){ string } + value: (number){ number } + }) } 1: (#struct){ id: (string){ "bar" } value: (int){ 80 } @@ -1031,13 +845,11 @@ } } } - issue3149: (_|_){ - // [eval] + issue3149: (struct){ #valid: (#struct){ name!: (string){ |((string){ &(=~"^Foo", =~"Foo$") }, (string){ "an exception" }) } } - list: (_|_){ - // [eval] + list: (#list){ 0: (#struct){ name: (string){ "FooBarFoo" } } @@ -1047,19 +859,8 @@ 2: (#struct){ name: (string){ "FooQuuxFoo" } } - 3: (_|_){ - // [eval] - name: (_|_){ - // [eval] issue3149.list.3.name: 2 errors in empty disjunction: - // issue3149.list.3.name: invalid value "an exception" (out of bound =~"^Foo"): - // ./issue3149.cue:3:13 - // ./issue3149.cue:3:10 - // ./issue3149.cue:10:10 - // issue3149.list.3.name: invalid value "an exception" (out of bound =~"Foo$"): - // ./issue3149.cue:3:46 - // ./issue3149.cue:3:10 - // ./issue3149.cue:10:10 - } + 3: (#struct){ + name: (string){ "an exception" } } } } @@ -1134,10 +935,10 @@ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } c: (#struct){ - v: (string){ |(*(string){ "a" }, *(string){ "b" }, *(string){ "c" }) } + v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } coo: (#struct){ - v: (string){ |(*(string){ "a" }, *(string){ "b" }, *(string){ "c" }) } + v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } } } -- out/eval/stats -- Leaks: 4 Freed: 2684 Reused: 2668 Allocs: 20 Retain: 118 Unifications: 1350 Conjuncts: 3905 Disjuncts: 2802 -- diff/todo/p1 -- issue2263.full: missing elimination, may be lack of closeContext -- diff/todo/p2 -- noChildError.issue1808.#type: one disjunction options eliminated due to earlier detected structural cycle. May be okay, but investigate. issue2209.simplified.full._X: ditto -- diff/todo/p3 -- issue2209.simplified.t2.BAZ: error reported in wrong location. -- diff/explanation -- issue2209.simplified.t3: new evaluator fixes known bug. preserveClosedness.medium.p*: discarding of default is correct. issue1417: new evaluator fixes known bug issue3149: new evaluator fixes known bug issue770: new evaluator fixes a bug in "c" and "coo" where defaults did not apply correctly. -- out/eval -- Errors: issue1417.ids.2: 2 errors in empty disjunction: issue2209.full.Bar.resource.spec: 6 errors in empty disjunction: issue2209.full.Bar.resource.spec.minBar: 2 errors in empty disjunction: issue2209.full.Bar.resource.spec.minBar: conflicting values null and int (mismatched types null and int): ./issue2209full.cue:43:7 ./issue2209full.cue:48:13 ./issue2209full.cue:67:10 ./issue2209full.cue:83:16 ./issue2209full.cue:87:13 ./issue2209full.cue:107:20 issue2209.full.Bar.resource.spec.minFoo: 2 errors in empty disjunction: issue2209.full.Bar.resource.spec.minFoo: conflicting values null and 10 (mismatched types null and int): ./issue2209full.cue:43:7 ./issue2209full.cue:48:13 ./issue2209full.cue:55:16 ./issue2209full.cue:71:4 ./issue2209full.cue:72:13 ./issue2209full.cue:92:13 issue2209.full.Bar.resource.spec.minFoo: conflicting values null and int (mismatched types null and int): ./issue2209full.cue:43:7 ./issue2209full.cue:48:13 ./issue2209full.cue:67:10 ./issue2209full.cue:83:16 ./issue2209full.cue:92:13 ./issue2209full.cue:105:20 issue3149.list.3.name: 2 errors in empty disjunction: issue1417.ids.1: invalid value "ab" (out of bound !~"^a"): ./issue1417.cue:2:7 ./issue1417.cue:4:11 ./issue1417.cue:4:26 issue1417.ids.2: invalid value "aB" (out of bound !~"^a"): ./issue1417.cue:2:7 ./issue1417.cue:4:11 ./issue1417.cue:4:32 issue1417.ids.2: invalid value "aB" (out of bound !~"[A-Z]"): ./issue1417.cue:3:16 ./issue1417.cue:4:11 ./issue1417.cue:4:32 issue2209.simplified.t3.BAZ: undefined field: y: ./issue2209full.cue:35:9 issue2209.full.Bar.resource.spec.minBar: undefined field: min: ./issue2209full.cue:77:25 issue3149.list.3.name: invalid value "an exception" (out of bound =~"^Foo"): ./issue3149.cue:3:13 ./issue3149.cue:3:10 ./issue3149.cue:10:10 issue3149.list.3.name: invalid value "an exception" (out of bound =~"Foo$"): ./issue3149.cue:3:46 ./issue3149.cue:3:10 ./issue3149.cue:10:10 Result: (_|_){ // [eval] disambiguateClosed: (struct){ b: (#struct){ |((#struct){ x: (bool){ true } }, (#struct){ y: (bool){ true } }) } a: (#struct){ |((#struct){ x: (bool){ true } }, (#struct){ y: (bool){ true } }) } #Def: (#struct){ |((#struct){ x: (bool){ true } }, (#struct){ y: (bool){ true } }) } } alwaysCheckMatchers1: (struct){ b: (struct){ c: (string){ "yyyyy" } } } alwaysCheckPatterns2: (struct){ a: (#struct){ c: (string){ "yyyyy" } } b: (#struct){ c: (string){ "yyyyy" } } #X: ((string|struct)){ |((string){ string }, (#struct){ c: (string){ string } }) } } nestedNonMonotonic: (struct){ resolved: (struct){ n1: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ c: (int){ 1 } d: (int){ 1 } } }, (null){ null }) } } n2: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (struct){ c: (int){ 1 } d: (int){ 1 } } } }, (null){ null }) } } } eliminated: (struct){ n1: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } } n2: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } } } incomplete: (struct){ a: (struct){ n1: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } } n2: (struct){ p1: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ // [incomplete] nestedNonMonotonic.incomplete.a.n2.p1.x.a.b: invalid value {c:1} (does not satisfy struct.MinFields(2)): len(fields) < MinFields(2) (1 < 2): // ./in.cue:96:15 // ./in.cue:96:32 // ./in.cue:97:12 c: (int){ 1 } } } }, (null){ null }) } } p2: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ // [incomplete] nestedNonMonotonic.incomplete.a.n2.p2.x.a.b: invalid value {c:1} (does not satisfy struct.MinFields(2)): len(fields) < MinFields(2) (1 < 2): // ./in.cue:102:15 // ./in.cue:101:12 // ./in.cue:102:32 c: (int){ 1 } } } }, (null){ null }) } } } } b: (struct){ n1: (struct){ p1: (struct){ x: (null){ null } } p2: (struct){ x: (null){ null } } p3: (struct){ x: (null){ null } } } n2: (struct){ p1: (struct){ x: ((null|struct)){ |((struct){ a: (struct){ b: (_|_){ // [incomplete] nestedNonMonotonic.incomplete.b.n2.p1.x.a.b: invalid value {c:1 & 1 & 1,d:1 & 1 & 1} (does not satisfy struct.MinFields(3)): len(fields) < MinFields(3) (2 < 3): // ./in.cue:138:15 // ./in.cue:124:15 // ./in.cue:125:12 // ./in.cue:126:12 // ./in.cue:130:12 // ./in.cue:131:15 // ./in.cue:132:12 // ./in.cue:136:12 // ./in.cue:137:12 // ./in.cue:138:32 c: (int){ 1 } d: (int){ 1 } } } }, (null){ null }) } } } } } } preserveClosedness: (struct){ small: (struct){ p1: (struct){ #A: (#struct){ |(*(#struct){ a: (string){ string } }, (#struct){ a: (string){ string } b: (int){ int } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ b: (int){ int } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } b: (int){ int } }) } } p2: (struct){ #A: (#struct){ |(*(#struct){ a: (string){ string } }, (#struct){ a: (string){ string } b: (int){ int } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ a: (string){ string } b: (int){ int } }, (#struct){ a: (string){ string } }, (#struct){ b: (int){ int } }) } } } medium: (struct){ p1: (struct){ #A: (#struct){ |(*(#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ c: (int){ int } }, (#struct){ d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (int){ int } }, (#struct){ b: (string){ string } d: (string){ string } }) } } p2: (struct){ #A: (#struct){ |(*(#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ c: (int){ int } }, (#struct){ d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (int){ int } }, (#struct){ b: (string){ string } d: (string){ string } }) } } p3: (struct){ #A: (#struct){ |(*(#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }) } #B: (#struct){ |(*(#struct){ }, (#struct){ a: (string){ string } c: (int){ int } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (int){ int } }, (#struct){ b: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ c: (int){ int } }, (#struct){ d: (string){ string } }) } } } } noChildError: (struct){ issue1608: (struct){ myValue: (#struct){ fieldName: (string){ "some string" } } #type: (#struct){ fieldName: ((string|struct)){ |((string){ string }, (#struct){ foo: (string){ string } }, (#struct){ bar: ((string|struct)){ |((string){ string }, (#struct){ foo: (string){ string } }) } }) } } #subtype: ((string|struct)){ |((string){ string }, (#struct){ foo: (string){ string } }) } } t1: (struct){ #D: (#struct){ b: (string){ string } } o: (#struct){ b: (string){ "test" } } } t2: (struct){ o: (#struct){ b: (string){ "test" } } #D: (#struct){ b: (string){ string } } } t3: (struct){ #D: (#struct){ |((#struct){ a: (null){ null } }, (#struct){ b: (string){ string } }) } o: (#struct){ b: (string){ "test" } } } t4: (struct){ o: (#struct){ b: (string){ "test" } } #D: (#struct){ |((#struct){ a: (null){ null } }, (#struct){ b: (string){ string } }) } } } issue1924: (struct){ t1: (struct){ m: (struct){ a: (int){ 2 } } x: (int){ 2 } } t2: (struct){ m: (struct){ a: (int){ 2 } } x: (int){ 3 } } t3: (struct){ m: (struct){ a: (int){ 2 } } x: (int){ 1 } } } issue1838: (struct){ t1: (struct){ p?: (#list){ } a: (null){ null } } t2: (struct){ p?: (#list){ } a: (null){ null } } } noHang: (struct){ #T: (list){ 0: (string){ "d" } } x: (list){ 0: (string){ "d" } } #X: (list){ 0: (string){ "d" } } } issue1940: (struct){ #T: (#list){ 0: (string){ "d" } 1: (list){ } } #A: (#struct){ type: (#list){ 0: (string){ "d" } 1: (list){ } } } #B: (#struct){ } #C: (#struct){ x: (#struct){ type: (#list){ 0: (string){ "d" } 1: (list){ } } } } } issue1417: (_|_){ // [eval] #ID: (string){ |((string){ &(!~"^a", =~"^a") }, (string){ &(!~"^a", !~"[A-Z]") }, (string){ &(=~"^ab$", =~"^a") }, (string){ &(=~"^ab$", !~"[A-Z]") }, (string){ &(=~"^aB$", =~"^a") }, (string){ &(=~"^aB$", !~"[A-Z]") }) } ids: (_|_){ // [eval] 0: (string){ "xyz" } 1: (_|_){ // [eval] issue1417.ids.1: invalid value "ab" (out of bound !~"^a"): // ./issue1417.cue:2:7 // ./issue1417.cue:4:11 // ./issue1417.cue:4:26 } 2: (_|_){ // [eval] issue1417.ids.2: 2 errors in empty disjunction: // issue1417.ids.2: invalid value "aB" (out of bound !~"^a"): // ./issue1417.cue:2:7 // ./issue1417.cue:4:11 // ./issue1417.cue:4:32 // issue1417.ids.2: invalid value "aB" (out of bound !~"[A-Z]"): // ./issue1417.cue:3:16 // ./issue1417.cue:4:11 // ./issue1417.cue:4:32 } } } issue2209: (_|_){ // [eval] simplified: (_|_){ // [eval] t1: (struct){ #SpecFoo: (#struct){ foo: (#struct){ min: (int){ 1 } } } #SpecBar: (#struct){ bar: (#struct){ min: (int){ 1 } } } spec: (#struct){ bar: (#struct){ min: (int){ 1 } } } out: (struct){ |((struct){ X: (#struct){ bar: (#struct){ min: (int){ 1 } } } nullFoo: (null){ null } minFoo: (int){ int } }, (struct){ minBar: (int){ int } X: (#struct){ bar: (#struct){ min: (int){ 1 } } } nullFoo: (null){ null } }, (struct){ X: (#struct){ bar: (#struct){ min: (int){ 1 } } } nullBar: (null){ null } minFoo: (int){ int } }, (struct){ minBar: (int){ int } X: (#struct){ bar: (#struct){ min: (int){ 1 } } } nullBar: (null){ null } }) } } t2: (_|_){ // [incomplete] issue2209.simplified.t2.BAZ: undefined field: x: // ./issue2209full.cue:24:17 #SpecFoo: (#struct){ foo: (#struct){ } } #SpecBar: (#struct){ bar: (#struct){ x: (int){ 1 } } } spec: (#struct){ |(*(#struct){ bar: (struct){ } foo: (#struct){ } }, (#struct){ bar: (#struct){ x: (int){ 1 } } }) } BAZ: (_|_){ // [incomplete] issue2209.simplified.t2.BAZ: undefined field: x: // ./issue2209full.cue:24:17 } b2: (int){ int } } t3: (_|_){ // [eval] issue2209.simplified.t3.BAZ: undefined field: y: // ./issue2209full.cue:35:9 #A: (#struct){ v: (int){ 1 } } BAZ: (_|_){ // [eval] issue2209.simplified.t3.BAZ: undefined field: y: // ./issue2209full.cue:35:9 } S: (#struct){ |(*(#struct){ x: (int){ 1 } v: (int){ 1 } }, (#struct){ x: (int){ 1 } y: (int){ 1 } }) } #B: (#struct){ x: (int){ 1 } y: (int){ 1 } } b2: (int){ int } } } full: (_|_){ // [eval] Foo: (#struct){ spec: (#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } } resource: (#struct){ spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } _X: (#struct){ spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ foo: (#struct){ } bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } } } } Bar: (_|_){ // [eval] spec: (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } } resource: (_|_){ // [eval] spec: (_|_){ // [eval] issue2209.full.Bar.resource.spec: 6 errors in empty disjunction: // issue2209.full.Bar.resource.spec.minBar: 2 errors in empty disjunction: // issue2209.full.Bar.resource.spec.minBar: conflicting values null and int (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:67:10 // ./issue2209full.cue:83:16 // ./issue2209full.cue:87:13 // ./issue2209full.cue:107:20 // issue2209.full.Bar.resource.spec.minFoo: 2 errors in empty disjunction: // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and 10 (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:55:16 // ./issue2209full.cue:71:4 // ./issue2209full.cue:72:13 // ./issue2209full.cue:92:13 // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and int (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:67:10 // ./issue2209full.cue:83:16 // ./issue2209full.cue:92:13 // ./issue2209full.cue:105:20 // issue2209.full.Bar.resource.spec.minBar: undefined field: min: // ./issue2209full.cue:77:25 minFoo: (_|_){ // [eval] issue2209.full.Bar.resource.spec.minFoo: 2 errors in empty disjunction: // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and 10 (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:55:16 // ./issue2209full.cue:71:4 // ./issue2209full.cue:72:13 // ./issue2209full.cue:92:13 // issue2209.full.Bar.resource.spec.minFoo: conflicting values null and int (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:67:10 // ./issue2209full.cue:83:16 // ./issue2209full.cue:92:13 // ./issue2209full.cue:105:20 } maxFoo: (_|_){ // [eval] issue2209.full.Bar.resource.spec.maxFoo: 2 errors in empty disjunction: // issue2209.full.Bar.resource.spec.maxFoo: conflicting values null and 20 (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:56:16 // ./issue2209full.cue:71:4 // ./issue2209full.cue:73:13 // ./issue2209full.cue:93:13 // issue2209.full.Bar.resource.spec.maxFoo: conflicting values null and int (mismatched types null and int): // ./issue2209full.cue:43:7 // ./issue2209full.cue:48:13 // ./issue2209full.cue:67:10 // ./issue2209full.cue:83:16 // ./issue2209full.cue:93:13 // ./issue2209full.cue:106:20 } minBar: (_|_){ // [eval] issue2209.full.Bar.resource.spec.minBar: undefined field: min: // ./issue2209full.cue:77:25 } maxBar: (_|_){ // [eval] issue2209.full.Bar.resource.spec.maxBar: undefined field: max: // ./issue2209full.cue:78:25 } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } } _X: (#struct){ spec: (#struct){ |(*(#struct){ bar: (#struct){ } foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } } } } #Abstract: (#struct){ spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } resource: (#struct){ spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } _X: (#struct){ spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } } } } _#Spec: (#struct){ |(*(#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } }, (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } }) } _#SpecFoo: (#struct){ foo: (#struct){ min: (int){ |(*(int){ 10 }, (int){ int }) } max: (int){ |(*(int){ 20 }, (int){ int }) } } } _#SpecBar: (#struct){ bar: (#struct){ min: (int){ |(*(int){ 30 }, (int){ int }) } max: (int){ |(*(int){ 40 }, (int){ int }) } } } _Thing: (#struct){ spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, *(#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }, (#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } _X: (_){ _ } } #Constrained: (#struct){ spec: (#struct){ |(*(#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, *(#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: (null){ null } }, (#struct){ minFoo: (int){ |(*(int){ 10 }, (int){ int }) } maxFoo: (int){ |(*(int){ 20 }, (int){ int }) } minBar?: (null){ null } maxBar?: (null){ null } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }, (#struct){ minFoo?: (null){ null } maxFoo?: (null){ null } minBar: (int){ |(*(int){ 30 }, (int){ int }) } maxBar: (int){ |(*(int){ 40 }, (int){ int }) } hoge?: (null){ null } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } }) } } #Base: (#struct){ spec: (#struct){ minFoo?: ((null|int)){ |((null){ null }, (int){ int }) } maxFoo?: ((null|int)){ |((null){ null }, (int){ int }) } minBar?: ((null|int)){ |((null){ null }, (int){ int }) } maxBar?: ((null|int)){ |((null){ null }, (int){ int }) } hoge?: ((null|bool)){ |((null){ null }, (bool){ bool }) } fuga?: ((null|bool)){ |((null){ null }, (bool){ bool }) } } } } } issue2246: (struct){ simplified: (struct){ #FormFoo: (#struct){ fooID: (string){ string } } #FormBar: (#struct){ barID: (string){ string } } #Form: (#struct){ |((#struct){ fooID: (string){ string } }, (#struct){ barID: (string){ string } }) } data: (struct){ fooID: (string){ "123" } } out1: (#struct){ fooID: (string){ "123" } } out2: (#struct){ fooID: (string){ "123" } } } full: (struct){ data: (struct){ forms: (#list){ 0: (struct){ fooID: (string){ "00-0000001" } } } } form1040: (#list){ 0: (int){ 3 } } #K1: (#struct){ #_base: (#struct){ common: (int){ 3 } } #FormFoo: (#struct){ common: (int){ 3 } fooID: (string){ string } } #FormBar: (#struct){ common: (int){ 3 } barID: (string){ string } } #Form: (#struct){ |((#struct){ common: (int){ 3 } fooID: (string){ string } }, (#struct){ common: (int){ 3 } barID: (string){ string } }) } } #Input: (#struct){ forms: (list){ } } #summarizeReturn: (#struct){ in: (#struct){ forms: (list){ } } out: (#list){ } } #compute: (#struct){ in: (#struct){ forms: (list){ } } out: (#list){ } } } } issue2263: (struct){ simplified: (struct){ metrics: (#struct){ id: (string){ "foo" } avg: (int){ 60 } } #Metric: (#struct){ |((#struct){ id: (string){ string } avg: (number){ number } }, (#struct){ id: (string){ string } }, (#struct){ avg: (number){ number } }, (#struct){ }) } #IDSource: (#struct){ id: (string){ string } } #TargetAverage: (#struct){ avg: (number){ number } } } full: (struct){ metrics: (#list){ 0: (#struct){ id: (string){ "foo" } avg: (int){ 60 } } 1: (#struct){ id: (string){ "bar" } value: (int){ 80 } } 2: (#struct){ uri: (string){ "baz" } avg: (int){ 70 } } 3: (#struct){ uri: (string){ "qux" } value: (int){ 90 } } } #Metric: (#struct){ |((#struct){ id: (string){ string } avg: (number){ number } }, (#struct){ id: (string){ string } value: (number){ number } }, (#struct){ uri: (string){ string } avg: (number){ number } }, (#struct){ uri: (string){ string } value: (number){ number } }) } #Source: (#struct){ |((#struct){ id: (string){ string } }, (#struct){ uri: (string){ string } }) } #Target: (#struct){ |((#struct){ avg: (number){ number } }, (#struct){ value: (number){ number } }) } #IDSource: (#struct){ id: (string){ string } } #URISource: (#struct){ uri: (string){ string } } #TargetAverage: (#struct){ avg: (number){ number } } #TargetValue: (#struct){ value: (number){ number } } } } issue3149: (_|_){ // [eval] #valid: (#struct){ name!: (string){ |((string){ &(=~"^Foo", =~"Foo$") }, (string){ "an exception" }) } } list: (_|_){ // [eval] 0: (#struct){ name: (string){ "FooBarFoo" } } 1: (#struct){ name: (string){ "FooBazFoo" } } 2: (#struct){ name: (string){ "FooQuuxFoo" } } 3: (_|_){ // [eval] name: (_|_){ // [eval] issue3149.list.3.name: 2 errors in empty disjunction: // issue3149.list.3.name: invalid value "an exception" (out of bound =~"^Foo"): // ./issue3149.cue:3:13 // ./issue3149.cue:3:10 // ./issue3149.cue:10:10 // issue3149.list.3.name: invalid value "an exception" (out of bound =~"Foo$"): // ./issue3149.cue:3:46 // ./issue3149.cue:3:10 // ./issue3149.cue:10:10 } } } } issue3528: (struct){ original: (struct){ workflows: (#list){ 0: (#struct){ container: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ volumes?: (list){ } }) } } } test: (#struct){ container: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ volumes?: (list){ } }) } } #Workflow: (#struct){ container: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ volumes?: (list){ } }) } } } reduced: (struct){ a: (#struct){ A: (#struct){ } #a: ((int|struct)){ |((int){ 2 }, (#struct){ v: (int){ 1 } }) } } #A: (#struct){ A: (#struct){ } #a: ((int|struct)){ |((int){ 2 }, (#struct){ v: (int){ 1 } }) } } } counter: (struct){ } nested: (struct){ t1: ((int|struct)){ |((struct){ v: (int){ 1 } }, (int){ 2 }, (int){ 3 }) } t2: ((int|struct)){ |((struct){ v: (int){ 1 } }, (int){ 2 }) } } } issue770: (struct){ #A: (#struct){ v: (string){ |((string){ "a" }, (string){ "b" }, (string){ "c" }) } } h: (struct){ a: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } b: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } boo: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } c: (#struct){ v: (string){ |(*(string){ "a" }, *(string){ "b" }, *(string){ "c" }) } } coo: (#struct){ v: (string){ |(*(string){ "a" }, *(string){ "b" }, *(string){ "c" }) } } } } } -- out/compile -- --- in.cue { disambiguateClosed: { b: (〈0;#Def〉 & 〈0;a〉) a: 〈0;#Def〉 #Def: { ({ x: true }|{ y: true }) } } alwaysCheckMatchers1: { b: ({ [=~"^xxxx$"]: int }|null) b: ({ c: string }|null) b: { c: "yyyyy" } } alwaysCheckPatterns2: { a: 〈0;#X〉 a: 〈0;b〉 b: 〈0;#X〉 b: { c: "yyyyy" } #X: (string|{ c: string { [=~"^xxxx$"]: int } }) } nestedNonMonotonic: { resolved: { n1: { x: ({ a: 〈import;struct〉.MinFields(2) }|null) x: ({ a: { c: 1 } }|null) x: ({ a: { d: 1 } }|null) } } } nestedNonMonotonic: { resolved: { n2: { x: ({ a: { b: 〈import;struct〉.MinFields(2) } }|null) x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: { d: 1 } } }|null) } } } nestedNonMonotonic: { eliminated: { n1: { p1: { x: ({ a: 〈import;struct〉.MaxFields(1) }|null) x: ({ a: { c: 1 } }|null) x: ({ a: { d: 1 } }|null) } } } } nestedNonMonotonic: { eliminated: { n1: { p2: { x: ({ a: { c: 1 } }|null) x: ({ a: 〈import;struct〉.MaxFields(1) }|null) x: ({ a: { d: 1 } }|null) } } } } nestedNonMonotonic: { eliminated: { n1: { p2: { x: ({ a: { c: 1 } }|null) x: ({ a: { d: 1 } }|null) x: ({ a: 〈import;struct〉.MaxFields(1) }|null) } } } } nestedNonMonotonic: { eliminated: { n2: { p1: { x: ({ a: { b: 〈import;struct〉.MaxFields(1) } }|null) x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: { d: 1 } } }|null) } } } } nestedNonMonotonic: { eliminated: { n2: { p2: { x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: 〈import;struct〉.MaxFields(1) } }|null) x: ({ a: { b: { d: 1 } } }|null) } } } } nestedNonMonotonic: { eliminated: { n2: { p2: { x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: { d: 1 } } }|null) x: ({ a: { b: 〈import;struct〉.MaxFields(1) } }|null) } } } } nestedNonMonotonic: { incomplete: { a: { n1: { p1: { x: ({ a: 〈import;struct〉.MinFields(2) }|null) x: ({ a: { c: 1 } }|null) } } } } } nestedNonMonotonic: { incomplete: { a: { n1: { p2: { x: ({ a: { c: 1 } }|null) x: ({ a: 〈import;struct〉.MinFields(2) }|null) } } } } } nestedNonMonotonic: { incomplete: { a: { n2: { p1: { x: ({ a: { b: 〈import;struct〉.MinFields(2) } }|null) x: ({ a: { b: { c: 1 } } }|null) } } } } } nestedNonMonotonic: { incomplete: { a: { n2: { p2: { x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: 〈import;struct〉.MinFields(2) } }|null) } } } } } nestedNonMonotonic: { incomplete: { b: { n1: { p1: { x: ({ a: 〈import;struct〉.MinFields(3) }|null) x: ({ a: { c: 1 } }|null) x: ({ a: { d: 1 } }|null) } } } } } nestedNonMonotonic: { incomplete: { b: { n1: { p2: { x: ({ a: { c: 1 } }|null) x: ({ a: 〈import;struct〉.MinFields(3) }|null) x: ({ a: { d: 1 } }|null) } } } } } nestedNonMonotonic: { incomplete: { b: { n1: { p3: { x: ({ a: { c: 1 } }|null) x: ({ a: { d: 1 } }|null) x: ({ a: 〈import;struct〉.MinFields(3) }|null) } } } } } nestedNonMonotonic: { incomplete: { b: { n2: { p1: { x: ({ a: { b: 〈import;struct〉.MinFields(3) } }|null) x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: { d: 1 } } }|null) } } } } } nestedNonMonotonic: { incomplete: { b: { n2: { p1: { x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: 〈import;struct〉.MinFields(3) } }|null) x: ({ a: { b: { d: 1 } } }|null) } } } } } nestedNonMonotonic: { incomplete: { b: { n2: { p1: { x: ({ a: { b: { c: 1 } } }|null) x: ({ a: { b: { d: 1 } } }|null) x: ({ a: { b: 〈import;struct〉.MinFields(3) } }|null) } } } } } preserveClosedness: { small: { p1: { #A: (〈0;#B〉 & { a: string }) #B: { (*{}|{ a: string }) (*{}|{ b: int }) } } } } preserveClosedness: { small: { p2: { #A: (〈0;#B〉 & { a: string }) #B: { ({ a: string }|*{}) (*{}|{ b: int }) } } } } preserveClosedness: { medium: { p1: { #A: (〈0;#B〉 & { a: string }) #B: { (*{}|{ a: string }|{ b: string }) (*{}|{ c: int }|{ d: string }) } } } } preserveClosedness: { medium: { p2: { #A: (〈0;#B〉 & { a: string }) #B: { ({ a: string }|*{}|{ b: string }) (*{}|{ c: int }|{ d: string }) } } } } preserveClosedness: { medium: { p3: { #A: (〈0;#B〉 & { a: string }) #B: { ({ a: string }|{ b: string }|*{}) (*{}|{ c: int }|{ d: string }) } } } } noChildError: _ noChildError: { issue1608: { myValue: (〈0;#type〉 & { fieldName: "some string" }) #type: { fieldName: 〈1;#subtype〉 } #subtype: (string|{ foo: string }|{ bar: 〈1;#subtype〉 }) } } noChildError: { t1: { #D: ({ b: string }|{ c: 〈1;#D〉 }) o: (〈0;#D〉 & { b: "test" }) } } noChildError: { t2: { o: (〈0;#D〉 & { b: "test" }) #D: ({ b: string }|{ c: 〈1;#D〉 }) } } noChildError: { t3: { #D: ({ a: null }|{ b: string }|{ c: 〈1;#D〉 }) o: (〈0;#D〉 & { b: "test" }) } } noChildError: { t4: { o: (〈0;#D〉 & { b: "test" }) #D: ({ a: null }|{ b: string }|{ c: 〈1;#D〉 }) } } issue1924: { t1: { m: { a: 2 } x: (*[ 〈1;m〉.b, ]|2) } } issue1924: { t2: { m: { a: 2 } x: (*{ v: 〈1;m〉.b }|3) } } issue1924: { t3: { m: { a: 2 } x: (*〈0;m〉.b|1) } } issue1838: { t1: { p?: [] a: ([ for _, k in 〈1;p〉 { 〈1;k〉 }, ]|null) } } issue1838: { t2: { p?: [] a: (null|[ for _, k in 〈1;p〉 { 〈1;k〉 }, ]) } } noHang: { #T: ([ "a", 〈1;#T〉, ]|[ "d", ...〈1;#T〉, ]) x: 〈0;#T〉 #X: 〈0;x〉 #X: 〈0;#T〉 } issue1940: { #T: ([ "a", 〈1;#T〉, ]|[ "b", 〈1;#T〉, ]|[ "c", 〈1;#T〉, ]|[ "d", [ ...〈2;#T〉, ], ]) #A: { type: 〈1;#T〉 } #B: { [string]: 〈1;#A〉 } #C: (〈0;#B〉 & { x: 〈1;#A〉 }) } } --- issue1417.cue { issue1417: { #ID: (!~"^a"|=~"^ab$"|=~"^aB$") #ID: (=~"^a"|!~"[A-Z]") ids: ([ ...〈1;#ID〉, ] & [ "xyz", "ab", "aB", ]) } } --- issue2209full.cue { issue2209: { simplified: { t1: { #SpecFoo: { foo: { min: 1 } } #SpecBar: { bar: { min: 1 } } spec: { bar: {} } spec: (〈0;#SpecFoo〉|〈0;#SpecBar〉) out: { ({ nullFoo: null }|{ nullBar: null }) ({ minFoo: int }|{ minBar: int }) if (〈0;X〉.bar != _|_(explicit error (_|_ literal) in source)) { minBar: 〈1;X〉.bar.min } X: 〈1;spec〉 } } } } issue2209: { simplified: { t2: { #SpecFoo: { foo: {} } #SpecBar: { bar: { x: 1 } } spec: { bar: {} } spec: (*〈0;#SpecFoo〉|〈0;#SpecBar〉) if (〈0;spec〉.bar != _|_(explicit error (_|_ literal) in source)) { BAZ: 〈1;spec〉.bar.x } ({ f1: int }|{ b2: int }) ({ f2: int }|{ b2: int }) } } } issue2209: { simplified: { t3: { #A: { v: 1 } ({ f1: int }|{ b2: int }) ({ f2: int }|{ b2: int }) BAZ: 〈0;S〉.y S: (*〈0;#A〉|〈0;#B〉) #B: { x: 1 y: 1 } S: { x: 1 } } } } issue2209: { full: { Foo: (〈0;#Abstract〉 & { spec: { foo: {} } }) Bar: (〈0;#Abstract〉 & { spec: { bar: {} } }) #Abstract: { spec: 〈1;_#Spec〉 resource: (〈1;_Thing〉 & { _X: { spec: 〈3〉.spec } }) } _#Spec: (*〈0;_#SpecFoo〉|〈0;_#SpecBar〉) _#SpecFoo: { foo: { min: (int|*10) max: (int|*20) } } _#SpecBar: { bar: { min: (int|*30) max: (int|*40) } } _Thing: (〈0;#Constrained〉 & { _X: _ spec: { if (〈1;_X〉.spec.foo != _|_(explicit error (_|_ literal) in source)) { minFoo: 〈2;_X〉.spec.foo.min maxFoo: 〈2;_X〉.spec.foo.max } if (〈1;_X〉.spec.bar != _|_(explicit error (_|_ literal) in source)) { minBar: 〈2;_X〉.spec.bar.min maxBar: 〈2;_X〉.spec.bar.max } } }) #Constrained: (〈0;#Base〉 & { spec: ({ minFoo: (int|*10) maxFoo: (int|*20) minBar?: null maxBar?: null }|{ minBar: (int|*30) maxBar: (int|*40) minFoo?: null maxFoo?: null }) spec: (*{ fuga?: null }|{ hoge?: null }) }) #Base: { spec: { minFoo?: (null|int) maxFoo?: (null|int) minBar?: (null|int) maxBar?: (null|int) hoge?: (null|bool) fuga?: (null|bool) } } } } } --- issue2246.cue { issue2246: { simplified: { #FormFoo: { fooID: string } #FormBar: { barID: string } #Form: { (〈1;#FormFoo〉|〈1;#FormBar〉) } data: { fooID: "123" } out1: (〈0;#Form〉 & 〈0;data〉) out2: (〈0;#Form〉 & 〈0;out1〉) } } issue2246: { full: { data: { forms: [ { fooID: "00-0000001" }, ] } form1040: (〈0;#compute〉 & { in: 〈1;data〉 }).out #K1: { #_base: { common: 3 } #FormFoo: { 〈1;#_base〉 fooID: string } #FormBar: { 〈1;#_base〉 barID: string } #Form: { (〈1;#FormFoo〉|〈1;#FormBar〉) } } #Input: { forms: [ ...〈2;#K1〉.#Form, ] } #summarizeReturn: { in: 〈1;#Input〉 out: [ for _, k in 〈1;in〉.forms { 〈1;k〉.common }, ] } #compute: { in: 〈1;#Input〉 out: (〈1;#summarizeReturn〉 & { in: 〈1;in〉 }).out } } } } --- issue2263.cue { issue2263: { simplified: { metrics: 〈0;#Metric〉 #Metric: { (〈1;#IDSource〉|{}) (〈1;#TargetAverage〉|{}) } metrics: { id: "foo" avg: 60 } #IDSource: { id: string } #TargetAverage: { avg: number } } } issue2263: { full: { metrics: [ ...〈1;#Metric〉, ] metrics: [ { id: "foo" avg: 60 }, { id: "bar" value: 80 }, { uri: "baz" avg: 70 }, { uri: "qux" value: 90 }, ] #Metric: { 〈1;#Source〉 〈1;#Target〉 } #Source: (〈0;#IDSource〉|〈0;#URISource〉) #Target: (〈0;#TargetAverage〉|〈0;#TargetValue〉) #IDSource: { id: string } #URISource: { uri: string } #TargetAverage: { avg: number } #TargetValue: { value: number } } } } --- issue3149.cue { issue3149: { #valid: { name!: ((=~"^Foo"|"an exception") & (=~"Foo$"|"an exception")) } list: [ ...〈1;#valid〉, ] list: [ { name: "FooBarFoo" }, { name: "FooBazFoo" }, { name: "FooQuuxFoo" }, { name: "an exception" }, ] } } --- issue3528.cue { issue3528: { original: { workflows: [ ...〈1;#Workflow〉, ] workflows: [ 〈1;test〉, ] test: (〈0;#Workflow〉 & {}) #Workflow: { container: { [string]: (string|〈1;#container〉) } #container: (string|{ volumes?: [ ...string, ] }) } } } issue3528: { reduced: { a?: 〈0;#A〉 a: (〈0;#A〉 & {}) #A: { A: { [string]: (1|〈1;#a〉) } #a: (2|{ v: 1 }) } } } issue3528: { counter: {} } issue3528: { nested: { t1: { ({ v: 1 }|(2|3)) ({ v: 1 }|(2|3)) ({ v: 1 }|(2|3)) ({ v: 1 }|(2|3)) } } } issue3528: { nested: { t2: { ({ v: 1 }|2) ({ v: 1 }|(2|3)) ({ v: 1 }|2) ({ v: 1 }|2) } } } } --- issue770.cue { issue770: { #A: { v: ("a"|"b"|"c") } h: { [string]: 〈1;#A〉 } h: { a: { v: (*"a"|string) } } h: { [=~"^b"]: { v: (*〈2;h〉.a.v|string) } } h: { [=~"^c"]: { v: (*〈2;h〉.b.v|string) } } h: { b: _ } h: { boo: _ } h: { c: _ } h: { coo: _ } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/embed.txtar000066400000000000000000000307051474664451600237460ustar00rootroot00000000000000-- in.cue -- // Given the existence of this field, embedDefault is a struct. This // means that embedding this conjunction into `embedDefault` itself should // make it resolve to `{a: 2}`. default: { y: *1 | {a: 2} y } unambiguous: { y: 1 | {a: 2} y } forDefault: { y: *1 | {a: 2} for x in [1] {y} } // Carry over default to first disjunct. openDefault: { #y: *1 | {a: 2} #y } openAmbiguous: { #y: 1 | {a: 2} #y } forceStruct: { #y: 1 | {a: 2} #y {} } defaultsMulti: { a: { #def: { *{} | {a: string} | {b: string} *{} | {c: string} | {d: string} } a: #def & {a: "foo"} } b: { #def: { *{} | {a: string} | {b: string} *{} | {c: string} | {d: string} *{} | {d: string} | {e: string} } a: #def & {a: "foo", e: "bar"} } } nested: { a: 1 | 2 | *( (3 | 4 | *( 5 | 6 | *7)) & ( 3 | 4 | ( *7 | 8 ))) } -- issue3415.cue -- issue3415: full: { A: #A & { i: { _a + _b _a: 1 _b: 10 } } #A: { i: *0 | number } } issue3415: reduced: { a: { 1 + #b #b: 10 } a: *0 | number } -- out/eval/stats -- Leaks: 19 Freed: 430 Reused: 413 Allocs: 36 Retain: 5 Unifications: 268 Conjuncts: 502 Disjuncts: 438 -- out/evalalpha -- (struct){ default: (struct){ y: ((int|struct)){ |(*(int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } unambiguous: (struct){ y: ((int|struct)){ |((int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } forDefault: (struct){ y: ((int|struct)){ |(*(int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } openDefault: ((int|struct)){ |(*(int){ 1 #y: ((int|struct)){ |(*(int){ 1 }, (#struct){ a: (int){ 2 } }) } }, (#struct){ #y: ((int|struct)){ |(*(int){ 1 }, (#struct){ a: (int){ 2 } }) } a: (int){ 2 } }) } openAmbiguous: ((int|struct)){ |((int){ 1 #y: ((int|struct)){ |((int){ 1 }, (#struct){ a: (int){ 2 } }) } }, (#struct){ #y: ((int|struct)){ |((int){ 1 }, (#struct){ a: (int){ 2 } }) } a: (int){ 2 } }) } forceStruct: (#struct){ #y: ((int|struct)){ |((int){ 1 }, (#struct){ a: (int){ 2 } }) } a: (int){ 2 } } defaultsMulti: (struct){ a: (struct){ #def: (#struct){ |(*(#struct){ }, (#struct){ c: (string){ string } }, (#struct){ d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } }, (#struct){ b: (string){ string } d: (string){ string } }) } a: (#struct){ |((#struct){ a: (string){ "foo" } }, (#struct){ a: (string){ "foo" } c: (string){ string } }, (#struct){ a: (string){ "foo" } d: (string){ string } }) } } b: (struct){ #def: (#struct){ |(*(#struct){ }, (#struct){ d: (string){ string } }, (#struct){ e: (string){ string } }, (#struct){ c: (string){ string } }, (#struct){ c: (string){ string } d: (string){ string } }, (#struct){ c: (string){ string } e: (string){ string } }, (#struct){ d: (string){ string } e: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } e: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } e: (string){ string } }, (#struct){ a: (string){ string } d: (string){ string } e: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } e: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } e: (string){ string } }, (#struct){ b: (string){ string } d: (string){ string } e: (string){ string } }) } a: (#struct){ |((#struct){ a: (string){ "foo" } e: (string){ "bar" } }, (#struct){ a: (string){ "foo" } e: (string){ "bar" } c: (string){ string } }, (#struct){ a: (string){ "foo" } e: (string){ "bar" } d: (string){ string } }) } } } nested: (struct){ a: (int){ |(*(int){ 7 }, (int){ 2 }, (int){ 3 }, (int){ 4 }, (int){ 1 }) } } issue3415: (struct){ full: (struct){ A: (#struct){ i: (int){ 11 _a: (int){ 1 } _b: (int){ 10 } } } #A: (#struct){ i: (number){ |(*(int){ 0 }, (number){ number }) } } } reduced: (struct){ a: (int){ 11 #b: (int){ 10 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -69,7 +69,7 @@ b: (string){ string } d: (string){ string } }) } - a: (#struct){ |(*(#struct){ + a: (#struct){ |((#struct){ a: (string){ "foo" } }, (#struct){ a: (string){ "foo" } @@ -143,7 +143,7 @@ d: (string){ string } e: (string){ string } }) } - a: (#struct){ |(*(#struct){ + a: (#struct){ |((#struct){ a: (string){ "foo" } e: (string){ "bar" } }, (#struct){ -- diff/explanation -- The old algorithm was incorrect: the default value should not be carried: only {b: string} of the first disjunction can be part of the result. As it is not a default, the result of the disjunction cross product cannot be a default either. -- out/eval -- (struct){ default: (struct){ y: ((int|struct)){ |(*(int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } unambiguous: (struct){ y: ((int|struct)){ |((int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } forDefault: (struct){ y: ((int|struct)){ |(*(int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } openDefault: ((int|struct)){ |(*(int){ 1 #y: ((int|struct)){ |(*(int){ 1 }, (#struct){ a: (int){ 2 } }) } }, (#struct){ #y: ((int|struct)){ |(*(int){ 1 }, (#struct){ a: (int){ 2 } }) } a: (int){ 2 } }) } openAmbiguous: ((int|struct)){ |((int){ 1 #y: ((int|struct)){ |((int){ 1 }, (#struct){ a: (int){ 2 } }) } }, (#struct){ #y: ((int|struct)){ |((int){ 1 }, (#struct){ a: (int){ 2 } }) } a: (int){ 2 } }) } forceStruct: (#struct){ #y: ((int|struct)){ |((int){ 1 }, (#struct){ a: (int){ 2 } }) } a: (int){ 2 } } defaultsMulti: (struct){ a: (struct){ #def: (#struct){ |(*(#struct){ }, (#struct){ c: (string){ string } }, (#struct){ d: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } }, (#struct){ b: (string){ string } d: (string){ string } }) } a: (#struct){ |(*(#struct){ a: (string){ "foo" } }, (#struct){ a: (string){ "foo" } c: (string){ string } }, (#struct){ a: (string){ "foo" } d: (string){ string } }) } } b: (struct){ #def: (#struct){ |(*(#struct){ }, (#struct){ d: (string){ string } }, (#struct){ e: (string){ string } }, (#struct){ c: (string){ string } }, (#struct){ c: (string){ string } d: (string){ string } }, (#struct){ c: (string){ string } e: (string){ string } }, (#struct){ d: (string){ string } e: (string){ string } }, (#struct){ a: (string){ string } }, (#struct){ a: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } e: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } d: (string){ string } }, (#struct){ a: (string){ string } c: (string){ string } e: (string){ string } }, (#struct){ a: (string){ string } d: (string){ string } e: (string){ string } }, (#struct){ b: (string){ string } }, (#struct){ b: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } e: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } d: (string){ string } }, (#struct){ b: (string){ string } c: (string){ string } e: (string){ string } }, (#struct){ b: (string){ string } d: (string){ string } e: (string){ string } }) } a: (#struct){ |(*(#struct){ a: (string){ "foo" } e: (string){ "bar" } }, (#struct){ a: (string){ "foo" } e: (string){ "bar" } c: (string){ string } }, (#struct){ a: (string){ "foo" } e: (string){ "bar" } d: (string){ string } }) } } } nested: (struct){ a: (int){ |(*(int){ 7 }, (int){ 2 }, (int){ 3 }, (int){ 4 }, (int){ 1 }) } } issue3415: (struct){ full: (struct){ A: (#struct){ i: (int){ 11 _a: (int){ 1 } _b: (int){ 10 } } } #A: (#struct){ i: (number){ |(*(int){ 0 }, (number){ number }) } } } reduced: (struct){ a: (int){ 11 #b: (int){ 10 } } } } } -- out/compile -- --- in.cue { default: { y: (*1|{ a: 2 }) 〈0;y〉 } unambiguous: { y: (1|{ a: 2 }) 〈0;y〉 } forDefault: { y: (*1|{ a: 2 }) for _, x in [ 1, ] { 〈2;y〉 } } openDefault: { #y: (*1|{ a: 2 }) 〈0;#y〉 } openAmbiguous: { #y: (1|{ a: 2 }) 〈0;#y〉 } forceStruct: { #y: (1|{ a: 2 }) 〈0;#y〉 {} } defaultsMulti: { a: { #def: { (*{}|{ a: string }|{ b: string }) (*{}|{ c: string }|{ d: string }) } a: (〈0;#def〉 & { a: "foo" }) } b: { #def: { (*{}|{ a: string }|{ b: string }) (*{}|{ c: string }|{ d: string }) (*{}|{ d: string }|{ e: string }) } a: (〈0;#def〉 & { a: "foo" e: "bar" }) } } nested: { a: (1|2|*((3|4|*(5|6|*7)) & (3|4|(*7|8)))) } } --- issue3415.cue { issue3415: { full: { A: (〈0;#A〉 & { i: { (〈0;_a〉 + 〈0;_b〉) _a: 1 _b: 10 } }) #A: { i: (*0|number) } } } issue3415: { reduced: { a: { (1 + 〈0;#b〉) #b: 10 } a: (*0|number) } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/errors.txtar000066400000000000000000000521431474664451600242060ustar00rootroot00000000000000-- in.cue -- issue570: { results: #DecodeOutput results: result: "hello" #Output: { result: _ } | { error: string } #DecodeOutput: #Output & { result?: [... string] ... } } issue516: { #Def: { match: metrics: string: {} } | {} x: #Def x: match: metrics: "foo": {} } // issue #465 explicitDefaultError: { a: string | *_|_ if a != "" { } } issue2916: { b: _ [_]: c: uint | *1 [string]: c: >=3 | *3 } issue3157: { foo: *42 | _ foo: *43 | bool } -- issue3581.cue -- issue3581: reduced: { list: [...] | *[] list: ["\(c)" ] c: _ } -- issue3576.cue -- issue3576: reduced: { #A: a!: string #B: { if false { dummy: {} } } foo: #B | #A foo: a: "1" } issue3576: full: { #Run: { run!: string options?: #Option | [#Option, ...] if options != _|_ { optionsValue: options } } #Copy: { copy!: string options?: #Option | [#Option, ...] if options != _|_ { optionsValue: options } } #Option: {} foo: #Run | #Copy foo: run: "make" } -- issue3599.cue -- // Ignore errors for irrelevant fields like let and optional fields. issue3599: full: { #Action: { action: { read!: string write?: _|_ } | { write!: string read?: _|_ } } #Minio: { container: #Action & { action: { read!: string write?: _|_ } | { write!: string read?: _|_ } } doWrite: bool | *true container: action: defaultAction defaultAction: { if doWrite { write: "somefile.txt" } if !doWrite { read: "somefile.txt" } } } } issue3599: reduced: p1: { { a?: 1&2 } | { a: string, b?: 1&2 } { } | { } } issue3599: reduced: p2: { { } | { } { a?: 1&2 } | { a: string, b?: 1&2 } } issue3599: let: { { } | { a: B | 1, let B = 1&2 } { } | { } } -- out/eval/stats -- Leaks: 6 Freed: 181 Reused: 171 Allocs: 16 Retain: 34 Unifications: 119 Conjuncts: 268 Disjuncts: 206 -- out/evalalpha -- Errors: issue516.x: 2 errors in empty disjunction: issue516.x.match: field not allowed: ./in.cue:23:5 issue516.x.match.metrics.foo: field not allowed: ./in.cue:23:21 issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): ./in.cue:3:19 ./in.cue:12:12 Result: (_|_){ // [eval] issue570: (_|_){ // [eval] results: (_|_){ // [eval] result: (_|_){ // [eval] issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): // ./in.cue:3:19 // ./in.cue:12:12 } } #Output: (#struct){ |((#struct){ result: (_){ _ } }, (#struct){ error: (string){ string } }) } #DecodeOutput: (#struct){ |((#struct){ result: (list){ } }, (#struct){ result?: (list){ } error: (string){ string } }) } } issue516: (_|_){ // [eval] #Def: (#struct){ |((#struct){ match: (#struct){ metrics: (#struct){ string: (#struct){ } } } }, (#struct){ }) } x: (_|_){ // [eval] issue516.x: 2 errors in empty disjunction: // issue516.x.match: field not allowed: // ./in.cue:23:5 // issue516.x.match.metrics.foo: field not allowed: // ./in.cue:23:21 match: (struct){ metrics: (struct){ foo: (struct){ } } } } } explicitDefaultError: (_|_){ // [incomplete] explicitDefaultError: non-concrete value string in operand to !=: // ./in.cue:30:5 // ./in.cue:28:5 a: (string){ string } } issue2916: (struct){ b: (struct){ c: (int){ |((int){ &(>=3, int) }, (int){ 3 }) } } } issue3157: (struct){ foo: ((bool|int)){ |((int){ 43 }, (bool){ bool }) } } issue3576: (struct){ reduced: (struct){ #A: (#struct){ a!: (string){ string } } #B: (#struct){ } foo: (#struct){ a: (string){ "1" } } } full: (struct){ #Run: (#struct){ run!: (string){ string } options?: ((list|struct)){ |((#struct){ }, (list){ 0: (#struct){ } }) } } #Copy: (#struct){ copy!: (string){ string } options?: ((list|struct)){ |((#struct){ }, (list){ 0: (#struct){ } }) } } #Option: (#struct){ } foo: (#struct){ run: (string){ "make" } options?: ((list|struct)){ |((#struct){ }, (list){ 0: (#struct){ } }) } } } } issue3581: (struct){ reduced: (struct){ list: (_|_){ // [incomplete] issue3581.reduced.list: 2 errors in empty disjunction: // issue3581.reduced.list: incompatible list lengths (0 and 1): // ./issue3581.cue:2:17 // issue3581.reduced.list.0: invalid interpolation: non-concrete value _ (type _): // ./issue3581.cue:3:9 0: (_){ _ } } c: (_){ _ } } } issue3599: (struct){ full: (struct){ #Action: (#struct){ action: (#struct){ |((#struct){ read!: (string){ string } write?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3599.cue:6:12 } }, (#struct){ write!: (string){ string } read?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3599.cue:9:12 } }) } } #Minio: (#struct){ container: (#struct){ action: (#struct){ write: (string){ "somefile.txt" } read?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3599.cue:9:12 // explicit error (_|_ literal) in source: // ./issue3599.cue:20:13 } } } doWrite: (bool){ |(*(bool){ true }, (bool){ bool }) } defaultAction: (#struct){ write: (string){ "somefile.txt" } } } } reduced: (struct){ p1: (struct){ |((struct){ a?: (_|_){ // [eval] issue3599.reduced.p1.a: conflicting values 2 and 1: // ./issue3599.cue:32:9 // ./issue3599.cue:32:11 } }, (struct){ a: (string){ string } b?: (_|_){ // [eval] issue3599.reduced.p1.b: conflicting values 2 and 1: // ./issue3599.cue:32:35 // ./issue3599.cue:32:37 } }) } p2: (struct){ |((struct){ a?: (_|_){ // [eval] issue3599.reduced.p2.a: conflicting values 2 and 1: // ./issue3599.cue:37:9 // ./issue3599.cue:37:11 } }, (struct){ a: (string){ string } b?: (_|_){ // [eval] issue3599.reduced.p2.b: conflicting values 2 and 1: // ./issue3599.cue:37:35 // ./issue3599.cue:37:37 } }) } } let: (struct){ |((struct){ }, (struct){ a: (int){ 1 } let B#1 = (_|_){ // [eval] issue3599.let.B: conflicting values 2 and 1: // ./issue3599.cue:40:29 // ./issue3599.cue:40:31 } }) } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,15 +1,10 @@ Errors: issue516.x: 2 errors in empty disjunction: issue516.x.match: field not allowed: - ./in.cue:20:6 - ./in.cue:22:5 ./in.cue:23:5 issue516.x.match.metrics.foo: field not allowed: - ./in.cue:19:19 - ./in.cue:22:5 ./in.cue:23:21 issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): - ./in.cue:2:11 ./in.cue:3:19 ./in.cue:12:12 @@ -19,17 +14,12 @@ issue570: (_|_){ // [eval] results: (_|_){ - // [eval] issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): - // ./in.cue:2:11 - // ./in.cue:3:19 - // ./in.cue:12:12 + // [eval] result: (_|_){ // [eval] issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): - // ./in.cue:2:11 // ./in.cue:3:19 // ./in.cue:12:12 } - error: (string){ string } } #Output: (#struct){ |((#struct){ result: (_){ _ } @@ -59,18 +49,10 @@ x: (_|_){ // [eval] issue516.x: 2 errors in empty disjunction: // issue516.x.match: field not allowed: - // ./in.cue:20:6 - // ./in.cue:22:5 // ./in.cue:23:5 // issue516.x.match.metrics.foo: field not allowed: - // ./in.cue:19:19 - // ./in.cue:22:5 // ./in.cue:23:21 - match: (_|_){ - // [eval] issue516.x.match: field not allowed: - // ./in.cue:20:6 - // ./in.cue:22:5 - // ./in.cue:23:5 + match: (struct){ metrics: (struct){ foo: (struct){ } @@ -86,11 +68,11 @@ } issue2916: (struct){ b: (struct){ - c: (int){ |(*(int){ 3 }, (int){ &(>=3, int) }) } + c: (int){ |((int){ &(>=3, int) }, (int){ 3 }) } } } issue3157: (struct){ - foo: ((bool|int)){ |(*(int){ 43 }, (bool){ bool }) } + foo: ((bool|int)){ |((int){ 43 }, (bool){ bool }) } } issue3576: (struct){ reduced: (struct){ @@ -136,13 +118,11 @@ reduced: (struct){ list: (_|_){ // [incomplete] issue3581.reduced.list: 2 errors in empty disjunction: - // issue3581.reduced.list: incompatible list lengths (0 and 1) + // issue3581.reduced.list: incompatible list lengths (0 and 1): + // ./issue3581.cue:2:17 // issue3581.reduced.list.0: invalid interpolation: non-concrete value _ (type _): // ./issue3581.cue:3:9 - 0: (_|_){ - // [incomplete] issue3581.reduced.list.0: invalid interpolation: non-concrete value _ (type _): - // ./issue3581.cue:3:9 - } + 0: (_){ _ } } c: (_){ _ } } @@ -186,7 +166,6 @@ p1: (struct){ |((struct){ a?: (_|_){ // [eval] issue3599.reduced.p1.a: conflicting values 2 and 1: - // ./issue3599.cue:32:2 // ./issue3599.cue:32:9 // ./issue3599.cue:32:11 } @@ -194,7 +173,6 @@ a: (string){ string } b?: (_|_){ // [eval] issue3599.reduced.p1.b: conflicting values 2 and 1: - // ./issue3599.cue:32:2 // ./issue3599.cue:32:35 // ./issue3599.cue:32:37 } @@ -202,7 +180,6 @@ p2: (struct){ |((struct){ a?: (_|_){ // [eval] issue3599.reduced.p2.a: conflicting values 2 and 1: - // ./issue3599.cue:37:2 // ./issue3599.cue:37:9 // ./issue3599.cue:37:11 } @@ -210,7 +187,6 @@ a: (string){ string } b?: (_|_){ // [eval] issue3599.reduced.p2.b: conflicting values 2 and 1: - // ./issue3599.cue:37:2 // ./issue3599.cue:37:35 // ./issue3599.cue:37:37 } @@ -221,7 +197,6 @@ a: (int){ 1 } let B#1 = (_|_){ // [eval] issue3599.let.B: conflicting values 2 and 1: - // ./issue3599.cue:40:2 // ./issue3599.cue:40:29 // ./issue3599.cue:40:31 } -- diff/todo/p3 -- Missing error positions. -- diff/explanation -- The additional "field not allowed" error is correct and a message corresponding to one of the conjuncts failing. issue516.x.match: changes are okay and arguably better. issue2916 and issue3157: the old evaluator incorrectly kept a default in the output. -- out/eval -- Errors: issue516.x: 2 errors in empty disjunction: issue516.x.match: field not allowed: ./in.cue:20:6 ./in.cue:22:5 ./in.cue:23:5 issue516.x.match.metrics.foo: field not allowed: ./in.cue:19:19 ./in.cue:22:5 ./in.cue:23:21 issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): ./in.cue:2:11 ./in.cue:3:19 ./in.cue:12:12 Result: (_|_){ // [eval] issue570: (_|_){ // [eval] results: (_|_){ // [eval] issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): // ./in.cue:2:11 // ./in.cue:3:19 // ./in.cue:12:12 result: (_|_){ // [eval] issue570.results.result: conflicting values "hello" and [...string] (mismatched types string and list): // ./in.cue:2:11 // ./in.cue:3:19 // ./in.cue:12:12 } error: (string){ string } } #Output: (#struct){ |((#struct){ result: (_){ _ } }, (#struct){ error: (string){ string } }) } #DecodeOutput: (#struct){ |((#struct){ result: (list){ } }, (#struct){ result?: (list){ } error: (string){ string } }) } } issue516: (_|_){ // [eval] #Def: (#struct){ |((#struct){ match: (#struct){ metrics: (#struct){ string: (#struct){ } } } }, (#struct){ }) } x: (_|_){ // [eval] issue516.x: 2 errors in empty disjunction: // issue516.x.match: field not allowed: // ./in.cue:20:6 // ./in.cue:22:5 // ./in.cue:23:5 // issue516.x.match.metrics.foo: field not allowed: // ./in.cue:19:19 // ./in.cue:22:5 // ./in.cue:23:21 match: (_|_){ // [eval] issue516.x.match: field not allowed: // ./in.cue:20:6 // ./in.cue:22:5 // ./in.cue:23:5 metrics: (struct){ foo: (struct){ } } } } } explicitDefaultError: (_|_){ // [incomplete] explicitDefaultError: non-concrete value string in operand to !=: // ./in.cue:30:5 // ./in.cue:28:5 a: (string){ string } } issue2916: (struct){ b: (struct){ c: (int){ |(*(int){ 3 }, (int){ &(>=3, int) }) } } } issue3157: (struct){ foo: ((bool|int)){ |(*(int){ 43 }, (bool){ bool }) } } issue3576: (struct){ reduced: (struct){ #A: (#struct){ a!: (string){ string } } #B: (#struct){ } foo: (#struct){ a: (string){ "1" } } } full: (struct){ #Run: (#struct){ run!: (string){ string } options?: ((list|struct)){ |((#struct){ }, (list){ 0: (#struct){ } }) } } #Copy: (#struct){ copy!: (string){ string } options?: ((list|struct)){ |((#struct){ }, (list){ 0: (#struct){ } }) } } #Option: (#struct){ } foo: (#struct){ run: (string){ "make" } options?: ((list|struct)){ |((#struct){ }, (list){ 0: (#struct){ } }) } } } } issue3581: (struct){ reduced: (struct){ list: (_|_){ // [incomplete] issue3581.reduced.list: 2 errors in empty disjunction: // issue3581.reduced.list: incompatible list lengths (0 and 1) // issue3581.reduced.list.0: invalid interpolation: non-concrete value _ (type _): // ./issue3581.cue:3:9 0: (_|_){ // [incomplete] issue3581.reduced.list.0: invalid interpolation: non-concrete value _ (type _): // ./issue3581.cue:3:9 } } c: (_){ _ } } } issue3599: (struct){ full: (struct){ #Action: (#struct){ action: (#struct){ |((#struct){ read!: (string){ string } write?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3599.cue:6:12 } }, (#struct){ write!: (string){ string } read?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3599.cue:9:12 } }) } } #Minio: (#struct){ container: (#struct){ action: (#struct){ write: (string){ "somefile.txt" } read?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3599.cue:9:12 // explicit error (_|_ literal) in source: // ./issue3599.cue:20:13 } } } doWrite: (bool){ |(*(bool){ true }, (bool){ bool }) } defaultAction: (#struct){ write: (string){ "somefile.txt" } } } } reduced: (struct){ p1: (struct){ |((struct){ a?: (_|_){ // [eval] issue3599.reduced.p1.a: conflicting values 2 and 1: // ./issue3599.cue:32:2 // ./issue3599.cue:32:9 // ./issue3599.cue:32:11 } }, (struct){ a: (string){ string } b?: (_|_){ // [eval] issue3599.reduced.p1.b: conflicting values 2 and 1: // ./issue3599.cue:32:2 // ./issue3599.cue:32:35 // ./issue3599.cue:32:37 } }) } p2: (struct){ |((struct){ a?: (_|_){ // [eval] issue3599.reduced.p2.a: conflicting values 2 and 1: // ./issue3599.cue:37:2 // ./issue3599.cue:37:9 // ./issue3599.cue:37:11 } }, (struct){ a: (string){ string } b?: (_|_){ // [eval] issue3599.reduced.p2.b: conflicting values 2 and 1: // ./issue3599.cue:37:2 // ./issue3599.cue:37:35 // ./issue3599.cue:37:37 } }) } } let: (struct){ |((struct){ }, (struct){ a: (int){ 1 } let B#1 = (_|_){ // [eval] issue3599.let.B: conflicting values 2 and 1: // ./issue3599.cue:40:2 // ./issue3599.cue:40:29 // ./issue3599.cue:40:31 } }) } } } -- out/compile -- --- in.cue { issue570: { results: 〈0;#DecodeOutput〉 results: { result: "hello" } #Output: ({ result: _ }|{ error: string }) #DecodeOutput: (〈0;#Output〉 & { result?: [ ...string, ] ... }) } issue516: { #Def: ({ match: { metrics: { string: {} } } }|{}) x: 〈0;#Def〉 x: { match: { metrics: { foo: {} } } } } explicitDefaultError: { a: (string|*_|_(explicit error (_|_ literal) in source)) if (〈0;a〉 != "") {} } issue2916: { b: _ [_]: { c: (&(int, >=0)|*1) } [string]: { c: (>=3|*3) } } issue3157: { foo: (*42|_) foo: (*43|bool) } } --- issue3576.cue { issue3576: { reduced: { #A: { a!: string } #B: { if false { dummy: {} } } foo: (〈0;#B〉|〈0;#A〉) foo: { a: "1" } } } issue3576: { full: { #Run: { run!: string options?: (〈1;#Option〉|[ 〈2;#Option〉, ..., ]) if (〈0;options〉 != _|_(explicit error (_|_ literal) in source)) { optionsValue: 〈1;options〉 } } #Copy: { copy!: string options?: (〈1;#Option〉|[ 〈2;#Option〉, ..., ]) if (〈0;options〉 != _|_(explicit error (_|_ literal) in source)) { optionsValue: 〈1;options〉 } } #Option: {} foo: (〈0;#Run〉|〈0;#Copy〉) foo: { run: "make" } } } } --- issue3581.cue { issue3581: { reduced: { list: ([ ..., ]|*[]) list: [ "\(〈1;c〉)", ] c: _ } } } --- issue3599.cue { issue3599: { full: { #Action: { action: ({ read!: string write?: _|_(explicit error (_|_ literal) in source) }|{ write!: string read?: _|_(explicit error (_|_ literal) in source) }) } #Minio: { container: (〈1;#Action〉 & { action: ({ read!: string write?: _|_(explicit error (_|_ literal) in source) }|{ write!: string read?: _|_(explicit error (_|_ literal) in source) }) }) doWrite: (bool|*true) container: { action: 〈1;defaultAction〉 } defaultAction: { if 〈1;doWrite〉 { write: "somefile.txt" } if !〈1;doWrite〉 { read: "somefile.txt" } } } } } issue3599: { reduced: { p1: { ({ a?: (1 & 2) }|{ a: string b?: (1 & 2) }) ({}|{}) } } } issue3599: { reduced: { p2: { ({}|{}) ({ a?: (1 & 2) }|{ a: string b?: (1 & 2) }) } } } issue3599: { let: { ({}|{ a: (〈0;let B#1〉|1) let B#1 = (1 & 2) }) ({}|{}) } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/incomplete.txtar000066400000000000000000000117511474664451600250310ustar00rootroot00000000000000-- in.cue -- import "encoding/yaml" issue700: { a: y: "y" test1: *a.x | 1 test2: *a.y | 1 } lookup: { x: { name: "Hello" } y: x.a ok1: *x.a | x ok2: x | *x.a ok3: x.a | *x ok4: *x | x.a ok5: x | x.a ok5: x.a | x allFail1: x.a | x.b allFail2: x.a | x.b } func: { s: string ok1: yaml.MarshalStream(s) | yaml.Marshal(s) } issue782: { a: { inner: string interpolation: *"\(inner)" | string interpolation: "override" } b: { inner: string interpolation: string | *"\(inner)" interpolation: "override" } c: { inner: string interpolation: "\(inner)" | string interpolation: "override" } d: { inner: string interpolation: string | "\(inner)" interpolation: "override" } } -- issue3680.cue -- issue3680: t1: { {} | { a?: _|_ b?: _|_ } {} | {} } issue3680: t2: { x: {} | { a?: _|_ b?: _|_ } x: {} | {} } -- out/eval/stats -- Leaks: 0 Freed: 98 Reused: 88 Allocs: 10 Retain: 0 Unifications: 56 Conjuncts: 132 Disjuncts: 98 -- out/eval -- (struct){ issue700: (struct){ a: (struct){ y: (string){ "y" } } test1: (int){ 1 } test2: ((int|string)){ |(*(string){ "y" }, (int){ 1 }) } } lookup: (struct){ x: (struct){ name: (string){ "Hello" } } y: (_|_){ // [incomplete] lookup.y: undefined field: a: // ./in.cue:13:14 } ok1: (struct){ name: (string){ "Hello" } } ok2: (struct){ name: (string){ "Hello" } } ok3: (struct){ name: (string){ "Hello" } } ok4: (struct){ name: (string){ "Hello" } } ok5: (struct){ name: (string){ "Hello" } } allFail1: (_|_){ // [incomplete] lookup.allFail1: 2 errors in empty disjunction: // lookup.allFail1: undefined field: a: // ./in.cue:20:14 // lookup.allFail1: undefined field: b: // ./in.cue:20:20 } allFail2: (_|_){ // [incomplete] lookup.allFail2: 2 errors in empty disjunction: // lookup.allFail2: undefined field: a: // ./in.cue:21:14 // lookup.allFail2: undefined field: b: // ./in.cue:21:20 } } func: (struct){ s: (string){ string } ok1: (_|_){ // [incomplete] func.ok1: 2 errors in empty disjunction: // func.ok1: non-concrete argument 0: // ./in.cue:26:7 // func.ok1: non-concrete argument 0: // ./in.cue:26:31 } } issue782: (struct){ a: (struct){ inner: (string){ string } interpolation: (string){ "override" } } b: (struct){ inner: (string){ string } interpolation: (string){ "override" } } c: (struct){ inner: (string){ string } interpolation: (string){ "override" } } d: (struct){ inner: (string){ string } interpolation: (string){ "override" } } } issue3680: (struct){ t1: (struct){ |((struct){ }, (struct){ a?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3680.cue:3:7 } b?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3680.cue:4:7 } }) } t2: (struct){ x: (struct){ |((struct){ }, (struct){ a?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3680.cue:10:7 } b?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./issue3680.cue:11:7 } }) } } } } -- out/compile -- --- in.cue { issue700: { a: { y: "y" } test1: (*〈0;a〉.x|1) test2: (*〈0;a〉.y|1) } lookup: { x: { name: "Hello" } y: 〈0;x〉.a ok1: (*〈0;x〉.a|〈0;x〉) ok2: (〈0;x〉|*〈0;x〉.a) ok3: (〈0;x〉.a|*〈0;x〉) ok4: (*〈0;x〉|〈0;x〉.a) ok5: (〈0;x〉|〈0;x〉.a) ok5: (〈0;x〉.a|〈0;x〉) allFail1: (〈0;x〉.a|〈0;x〉.b) allFail2: (〈0;x〉.a|〈0;x〉.b) } func: { s: string ok1: (〈import;"encoding/yaml"〉.MarshalStream(〈0;s〉)|〈import;"encoding/yaml"〉.Marshal(〈0;s〉)) } issue782: { a: { inner: string interpolation: (*"\(〈0;inner〉)"|string) interpolation: "override" } b: { inner: string interpolation: (string|*"\(〈0;inner〉)") interpolation: "override" } c: { inner: string interpolation: ("\(〈0;inner〉)"|string) interpolation: "override" } d: { inner: string interpolation: (string|"\(〈0;inner〉)") interpolation: "override" } } } --- issue3680.cue { issue3680: { t1: { ({}|{ a?: _|_(explicit error (_|_ literal) in source) b?: _|_(explicit error (_|_ literal) in source) }) ({}|{}) } } issue3680: { t2: { x: ({}|{ a?: _|_(explicit error (_|_ literal) in source) b?: _|_(explicit error (_|_ literal) in source) }) x: ({}|{}) } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/nested.txtar000066400000000000000000000074151474664451600241560ustar00rootroot00000000000000-- issue3635.cue -- import "list" issue3635: case1: { Run: { env: *{[string]: string} | [...string] } command: Run & { env: list.Concat([["foo"], ["bar"]]) } } issue3635: case2: { out: [...#Schema] out: [#Schema & { name: "x" }] #Schema: { name?: string container?: [string]: string | #container #container: string | { env?: #env } #env: [string]: bool | string } } issue3635: reduced: { out: {X} & X X: { b: int | c c: int | { e: d } } d: 1 } issue3635: reduced_noshare: { out: {X} & X X: { b: int | c c: int | { e: d & __no_sharing } } d: 1 } -- out/eval/stats -- Leaks: 0 Freed: 159 Reused: 145 Allocs: 14 Retain: 62 Unifications: 83 Conjuncts: 310 Disjuncts: 165 -- out/eval -- (struct){ issue3635: (struct){ case1: (struct){ Run: (struct){ env: ((list|struct)){ |(*(struct){ }, (list){ }) } } command: (struct){ env: (#list){ 0: (string){ "foo" } 1: (string){ "bar" } } } } case2: (struct){ out: (#list){ 0: (#struct){ name: (string){ "x" } container?: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ env?: (#struct){ } }) } #env: (#struct){ } } } #Schema: (#struct){ name?: (string){ string } container?: (#struct){ } #container: ((string|struct)){ |((string){ string }, (#struct){ env?: (#struct){ } }) } #env: (#struct){ } } } reduced: (struct){ out: (struct){ b: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } c: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } } X: (struct){ b: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } c: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } } d: (int){ 1 } } reduced_noshare: (struct){ out: (struct){ b: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } c: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } } X: (struct){ b: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } c: ((int|struct)){ |((int){ int }, (struct){ e: (int){ 1 } }) } } d: (int){ 1 } } } } -- out/compile -- --- issue3635.cue { issue3635: { case1: { Run: { env: (*{ [string]: string }|[ ...string, ]) } command: (〈0;Run〉 & { env: 〈import;list〉.Concat([ [ "foo", ], [ "bar", ], ]) }) } } issue3635: { case2: { out: [ ...〈1;#Schema〉, ] out: [ (〈1;#Schema〉 & { name: "x" }), ] #Schema: { name?: string container?: { [string]: (string|〈1;#container〉) } #container: (string|{ env?: 〈1;#env〉 }) #env: { [string]: (bool|string) } } } } issue3635: { reduced: { out: ({ 〈1;X〉 } & 〈0;X〉) X: { b: (int|〈0;c〉) c: (int|{ e: 〈2;d〉 }) } d: 1 } } issue3635: { reduced_noshare: { out: ({ 〈1;X〉 } & 〈0;X〉) X: { b: (int|〈0;c〉) c: (int|{ e: (〈2;d〉 & _|_(no sharing)) }) } d: 1 } } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/operands.txtar000066400000000000000000000031141474664451600244770ustar00rootroot00000000000000# This file tests disjunctions used as operands. -- in.cue -- list: *[1] | [2] condition: *true | false num: *1 | 2 object: *{a: 1} | {a: 2} forLoop: [ for e in list { "count: \(e)" }, ] conditional: { if condition { a: 3 } if num < 5 { b: 3 } } selector: { a: object.a } index: { a: list[0] } binOp: { a: num + 4 } unaryOp: { a: -num } -- out/eval/stats -- Leaks: 0 Freed: 30 Reused: 25 Allocs: 5 Retain: 0 Unifications: 22 Conjuncts: 33 Disjuncts: 30 -- out/eval -- (struct){ list: (list){ |(*(#list){ 0: (int){ 1 } }, (#list){ 0: (int){ 2 } }) } condition: (bool){ |(*(bool){ true }, (bool){ false }) } num: (int){ |(*(int){ 1 }, (int){ 2 }) } object: (struct){ |(*(struct){ a: (int){ 1 } }, (struct){ a: (int){ 2 } }) } forLoop: (#list){ 0: (string){ "count: 1" } } conditional: (struct){ a: (int){ 3 } b: (int){ 3 } } selector: (struct){ a: (int){ 1 } } index: (struct){ a: (int){ 1 } } binOp: (struct){ a: (int){ 5 } } unaryOp: (struct){ a: (int){ -1 } } } -- out/compile -- --- in.cue { list: (*[ 1, ]|[ 2, ]) condition: (*true|false) num: (*1|2) object: (*{ a: 1 }|{ a: 2 }) forLoop: [ for _, e in 〈1;list〉 { "count: \(〈1;e〉)" }, ] conditional: { if 〈1;condition〉 { a: 3 } if (〈1;num〉 < 5) { b: 3 } } selector: { a: 〈1;object〉.a } index: { a: 〈1;list〉[0] } binOp: { a: (〈1;num〉 + 4) } unaryOp: { a: -〈1;num〉 } } cue-lang-cue-db9cc73/cue/testdata/disjunctions/specdeviation.txtar000066400000000000000000000131431474664451600255240ustar00rootroot00000000000000It turns out the semantics of the spec is somewhat awkward, though theoretically nicer. It seems like we do need to change the definition somewhat to make it less awkward, or at least come up with a good workaround before adopting the spec. We have introduce a small hack to mimic the old behavior for scalar values. Note that the value of p below is now 2 (default), but should be the non-concrete 2 | int. Proof: p: *((*1 | int) & 2) | int // substitution of both P conjuncts in p p: *(*_|_ | 2) | int // U1: distribute conjuncts p: *_|_ | 2 | int // M2: remove mark p: 2 | int // value after removing default. -- in.cue -- Q: *1 | int q: *Q | int // 1 as expected P: *1 | int P: 2 p: *P | int // now 2, but should be (2 | int), according to the spec: // Here the inner default may not be used as it is masked by the outer default. r: (*3 | (*1 | 2)) & (1 | 2) // Here the inner default is used, as there are no defaults marked in the // outer disjunction. s: (3 | (*1 | 2)) & (1 | 2) s1: #Size & {min: 5} #Size: { max: >min | *min res: uint | *0 min: >res | *(1 + res) } staged: { c: ("a" | "b") & (*(*"a" | string) | string) d: (*(*"a" | string) | string) & ("a" | "b") } issue763a: { #A: { v: "a" | "b" | "c" // change to string to fix } h: [string]: #A h: [=~"^b"]: #A & { v: *h.a.v | string } h: a: { v: *"a" | string } h: baa: _ h: boo: _ } -- out/eval/stats -- Leaks: 0 Freed: 171 Reused: 158 Allocs: 13 Retain: 2 Unifications: 28 Conjuncts: 217 Disjuncts: 172 -- out/evalalpha -- (struct){ Q: (int){ |(*(int){ 1 }, (int){ int }) } q: (int){ |(*(int){ 1 }, (int){ int }) } P: (int){ 2 } p: (int){ |((int){ 2 }, (int){ int }) } r: (int){ |((int){ 1 }, (int){ 2 }) } s: (int){ |(*(int){ 1 }, (int){ 2 }) } s1: (#struct){ min: (int){ 5 } max: (number){ |((number){ >5 }, (int){ 5 }) } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } } #Size: (#struct){ max: (number){ |(*(int){ 1 }, (number){ >0 }, (number){ >1 }) } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (number){ |(*(int){ 1 }, (number){ >0 }) } } staged: (struct){ c: (string){ |(*(string){ "a" }, (string){ "b" }) } d: (string){ |(*(string){ "a" }, (string){ "b" }) } } issue763a: (struct){ #A: (#struct){ v: (string){ |((string){ "a" }, (string){ "b" }, (string){ "c" }) } } h: (struct){ a: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } baa: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } boo: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,13 +2,13 @@ Q: (int){ |(*(int){ 1 }, (int){ int }) } q: (int){ |(*(int){ 1 }, (int){ int }) } P: (int){ 2 } - p: (int){ |(*(int){ 2 }, (int){ int }) } + p: (int){ |((int){ 2 }, (int){ int }) } r: (int){ |((int){ 1 }, (int){ 2 }) } s: (int){ |(*(int){ 1 }, (int){ 2 }) } s1: (#struct){ - max: (number){ |(*(int){ 5 }, (number){ >5 }) } - res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 5 } + max: (number){ |((number){ >5 }, (int){ 5 }) } + res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } } #Size: (#struct){ max: (number){ |(*(int){ 1 }, (number){ >0 }, (number){ >1 }) } -- diff/explanation -- The changes in default behavior as are shown here are according to spec, as is described at the top of the file. These changes may pose too much of a problem for the transition to the new evaluator, though. TODO: consider reintroducing bugs. -- diff/todo/p3 -- Reordering. -- out/eval -- (struct){ Q: (int){ |(*(int){ 1 }, (int){ int }) } q: (int){ |(*(int){ 1 }, (int){ int }) } P: (int){ 2 } p: (int){ |(*(int){ 2 }, (int){ int }) } r: (int){ |((int){ 1 }, (int){ 2 }) } s: (int){ |(*(int){ 1 }, (int){ 2 }) } s1: (#struct){ max: (number){ |(*(int){ 5 }, (number){ >5 }) } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (int){ 5 } } #Size: (#struct){ max: (number){ |(*(int){ 1 }, (number){ >0 }, (number){ >1 }) } res: (int){ |(*(int){ 0 }, (int){ &(>=0, int) }) } min: (number){ |(*(int){ 1 }, (number){ >0 }) } } staged: (struct){ c: (string){ |(*(string){ "a" }, (string){ "b" }) } d: (string){ |(*(string){ "a" }, (string){ "b" }) } } issue763a: (struct){ #A: (#struct){ v: (string){ |((string){ "a" }, (string){ "b" }, (string){ "c" }) } } h: (struct){ a: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } baa: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } boo: (#struct){ v: (string){ |(*(string){ "a" }, (string){ "b" }, (string){ "c" }) } } } } } -- out/compile -- --- in.cue { Q: (*1|int) q: (*〈0;Q〉|int) P: (*1|int) P: 2 p: (*〈0;P〉|int) r: ((*3|(*1|2)) & (1|2)) s: ((3|(*1|2)) & (1|2)) s1: (〈0;#Size〉 & { min: 5 }) #Size: { max: (>〈0;min〉|*〈0;min〉) res: (&(int, >=0)|*0) min: (>〈0;res〉|*(1 + 〈0;res〉)) } staged: { c: (("a"|"b") & (*(*"a"|string)|string)) d: ((*(*"a"|string)|string) & ("a"|"b")) } issue763a: { #A: { v: ("a"|"b"|"c") } h: { [string]: 〈1;#A〉 } h: { [=~"^b"]: (〈1;#A〉 & { v: (*〈2;h〉.a.v|string) }) } h: { a: { v: (*"a"|string) } } h: { baa: _ } h: { boo: _ } } } cue-lang-cue-db9cc73/cue/testdata/eval/000077500000000000000000000000001474664451600200145ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/eval/basictypes.txtar000066400000000000000000000012101474664451600232400ustar00rootroot00000000000000-- in.cue -- top: { a: {_} b: _ } scalar: { a: {string} b: string c: {{{number}}} d: number } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 6 Allocs: 3 Retain: 0 Unifications: 9 Conjuncts: 14 Disjuncts: 9 -- out/eval -- (struct){ top: (struct){ a: (_){ _ } b: (_){ _ } } scalar: (struct){ a: (string){ string } b: (string){ string } c: (number){ number } d: (number){ number } } } -- out/compile -- --- in.cue { top: { a: { _ } b: _ } scalar: { a: { string } b: string c: { { { number } } } d: number } } cue-lang-cue-db9cc73/cue/testdata/eval/bounds.txtar000066400000000000000000001550621474664451600224030ustar00rootroot00000000000000-- in.cue -- x0: 5 x1: b5 & 30 b0: 0 b1: b0 & int b2: int & <5.5 b3: <10 & <=5 b4: >=20 & >20 b5: >=21 & >20 b6: int & >5 & <=6 simplifyExpr: { less1: <(<3) less2: <(<=3) less3: <=(<3) less4: <=(<=3) less5: <(!=3) less6: <=(!=3) gtr1: >(>3) gtr2: >(>=3) gtr3: >=(>3) gtr4: >=(>=3) gtr5: >(!=3) gtr6: >=(!=3) lg1: <(>3) lg2: <(>=3) lg3: <=(>3) lg4: <=(>=3) gl1: >(<3) gl2: >(<=3) gl3: >=(<3) gl4: >=(<=3) ne1: !=(!=3) ne2: !=(<3) ne3: !=(<=3) ne4: !=(>3) ne5: !=(>=3) s: string n: number i: int f: float b: bytes basic1: <(i) basic2: >(n) basic3: >=(s) basic4: <=(f) basic5: <=(b) // Do NOT interpret this the same as `!= type`. bne1: !=(s) bne2: !=(n) bne3: !=(n) bne4: !=(i) bne5: !=(b) e1: <(=~"foo") e2: >(null) } -- binarystring.cue -- simplifyBinary: strings: { err1: p1: <"a" & >"b" err1: p2: >"b" & <"a" err2: p1: >"b" & <="a" err2: p2: <="a" & >"b" err3: p1: >="b" & <"b" err3: p2: <"b" & >="b" err3: p3: >"b" & <="b" err3: p4: <="b" & >"b" ok1: p1: >"a" & <"b" ok1: p2: <"b" & >"a" ok2: p1: >"a" & <="b" ok2: p2: <="b" & >"a" ok2: p3: >="a" & <"b" ok2: p4: <"b" & >="a" ok3: p1: >="b" & <="c" ok3: p2: <="c" & >="b" ok4: p1: >="b" & <="b" } simplifyBinary: byte: { err1: p1: <'a' & >'b' err1: p2: >'b' & <'a' err2: p1: >'b' & <='a' err2: p2: <='a' & >'b' err3: p1: >='b' & <'b' err3: p2: <'b' & >='b' err3: p3: >'b' & <='b' err3: p4: <='b' & >'b' ok1: p1: >'a' & <'b' ok1: p2: <'b' & >'a' ok2: p1: >'a' & <='b' ok2: p2: <='b' & >'a' ok2: p3: >='a' & <'b' ok2: p4: <'b' & >='a' ok3: p1: >='b' & <='c' ok3: p2: <='c' & >='b' ok4: p1: >='b' & <='b' } -- binary.cue -- simplifyBinary: float: { err1: p1: <1 & >2 err1: p2: >2 & <1 err2: p1: >2 & <=1 err2: p2: <=1 & >2 err3: p1: >=2 & <2 err3: p2: <2 & >=2 err3: p3: >2 & <=2 err3: p4: <=2 & >2 ok1: p1: >1 & <2 ok1: p2: <2 & >1 ok2: p1: >=2 & <=2 ok2: p2: <=2 & >=2 } simplifyBinary: integer: { [_]: [_]: int err1: p1: <1 & >2 err1: p2: >2 & <1 err2: p1: >2 & <=1 err2: p2: <=1 & >2 err3: p1: >=2 & <2 err3: p2: <2 & >=2 err3: p3: >2 & <=2 err3: p4: <=2 & >2 err4: p1: >1 & <2 err4: p2: <2 & >1 ok1: p1: >=2 & <=3 ok1: p2: <=3 & >=2 ok2: p1: >=2 & <=2 ok2: p2: <=2 & >=2 ok3: p1: >=2 & <3 ok3: p2: >2 & <=3 ok3: p3: <3 & >=2 ok3: p4: <=3 & >2 } -- out/eval/stats -- Leaks: 0 Freed: 148 Reused: 143 Allocs: 5 Retain: 1 Unifications: 148 Conjuncts: 337 Disjuncts: 149 -- out/evalalpha -- Errors: simplifyBinary.float.err1.p1: incompatible number bounds <1 and >2: ./binary.cue:2:18 ./binary.cue:2:13 simplifyBinary.float.err1.p2: incompatible number bounds <1 and >2: ./binary.cue:3:18 ./binary.cue:3:13 simplifyBinary.float.err2.p1: incompatible number bounds <=1 and >2: ./binary.cue:5:18 ./binary.cue:5:13 simplifyBinary.float.err2.p2: incompatible number bounds <=1 and >2: ./binary.cue:6:19 ./binary.cue:6:13 simplifyBinary.float.err3.p1: incompatible number bounds <2 and >=2: ./binary.cue:8:19 ./binary.cue:8:13 simplifyBinary.float.err3.p2: incompatible number bounds <2 and >=2: ./binary.cue:9:18 ./binary.cue:9:13 simplifyBinary.float.err3.p3: incompatible number bounds <=2 and >2: ./binary.cue:10:18 ./binary.cue:10:13 simplifyBinary.float.err3.p4: incompatible number bounds <=2 and >2: ./binary.cue:11:19 ./binary.cue:11:13 simplifyBinary.integer.err1.p1: incompatible integer bounds <1 and >2: ./binary.cue:22:18 ./binary.cue:22:13 simplifyBinary.integer.err1.p2: incompatible integer bounds <1 and >2: ./binary.cue:23:18 ./binary.cue:23:13 simplifyBinary.integer.err2.p1: incompatible integer bounds <=1 and >2: ./binary.cue:25:18 ./binary.cue:25:13 simplifyBinary.integer.err2.p2: incompatible integer bounds <=1 and >2: ./binary.cue:26:19 ./binary.cue:26:13 simplifyBinary.integer.err3.p1: incompatible integer bounds <2 and >=2: ./binary.cue:28:19 ./binary.cue:28:13 simplifyBinary.integer.err3.p2: incompatible integer bounds <2 and >=2: ./binary.cue:29:18 ./binary.cue:29:13 simplifyBinary.integer.err3.p3: incompatible integer bounds <=2 and >2: ./binary.cue:30:18 ./binary.cue:30:13 simplifyBinary.integer.err3.p4: incompatible integer bounds <=2 and >2: ./binary.cue:31:19 ./binary.cue:31:13 simplifyBinary.integer.err4.p1: incompatible integer bounds >1 and <2: ./binary.cue:33:18 ./binary.cue:33:13 simplifyBinary.integer.err4.p2: incompatible integer bounds >1 and <2: ./binary.cue:34:18 ./binary.cue:34:13 simplifyBinary.strings.err1.p1: incompatible string bounds <"a" and >"b": ./binarystring.cue:2:20 ./binarystring.cue:2:13 simplifyBinary.strings.err1.p2: incompatible string bounds <"a" and >"b": ./binarystring.cue:3:20 ./binarystring.cue:3:13 simplifyBinary.strings.err2.p1: incompatible string bounds <="a" and >"b": ./binarystring.cue:5:20 ./binarystring.cue:5:13 simplifyBinary.strings.err2.p2: incompatible string bounds <="a" and >"b": ./binarystring.cue:6:21 ./binarystring.cue:6:13 simplifyBinary.strings.err3.p1: incompatible string bounds <"b" and >="b": ./binarystring.cue:8:21 ./binarystring.cue:8:13 simplifyBinary.strings.err3.p2: incompatible string bounds <"b" and >="b": ./binarystring.cue:9:20 ./binarystring.cue:9:13 simplifyBinary.strings.err3.p3: incompatible string bounds <="b" and >"b": ./binarystring.cue:10:20 ./binarystring.cue:10:13 simplifyBinary.strings.err3.p4: incompatible string bounds <="b" and >"b": ./binarystring.cue:11:21 ./binarystring.cue:11:13 simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': ./binarystring.cue:27:20 ./binarystring.cue:27:13 simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': ./binarystring.cue:28:20 ./binarystring.cue:28:13 simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': ./binarystring.cue:30:20 ./binarystring.cue:30:13 simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': ./binarystring.cue:31:21 ./binarystring.cue:31:13 simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': ./binarystring.cue:33:21 ./binarystring.cue:33:13 simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': ./binarystring.cue:34:20 ./binarystring.cue:34:13 simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': ./binarystring.cue:35:20 ./binarystring.cue:35:13 simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': ./binarystring.cue:36:21 ./binarystring.cue:36:13 simplifyExpr.e2: cannot use null for bound >: ./in.cue:62:8 Result: (_|_){ // [eval] simplifyBinary: (_|_){ // [eval] float: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err1.p1: incompatible number bounds <1 and >2: // ./binary.cue:2:18 // ./binary.cue:2:13 } p2: (_|_){ // [eval] simplifyBinary.float.err1.p2: incompatible number bounds <1 and >2: // ./binary.cue:3:18 // ./binary.cue:3:13 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err2.p1: incompatible number bounds <=1 and >2: // ./binary.cue:5:18 // ./binary.cue:5:13 } p2: (_|_){ // [eval] simplifyBinary.float.err2.p2: incompatible number bounds <=1 and >2: // ./binary.cue:6:19 // ./binary.cue:6:13 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err3.p1: incompatible number bounds <2 and >=2: // ./binary.cue:8:19 // ./binary.cue:8:13 } p2: (_|_){ // [eval] simplifyBinary.float.err3.p2: incompatible number bounds <2 and >=2: // ./binary.cue:9:18 // ./binary.cue:9:13 } p3: (_|_){ // [eval] simplifyBinary.float.err3.p3: incompatible number bounds <=2 and >2: // ./binary.cue:10:18 // ./binary.cue:10:13 } p4: (_|_){ // [eval] simplifyBinary.float.err3.p4: incompatible number bounds <=2 and >2: // ./binary.cue:11:19 // ./binary.cue:11:13 } } ok1: (struct){ p1: (number){ &(>1, <2) } p2: (number){ &(>1, <2) } } ok2: (struct){ p1: (number){ 2 } p2: (number){ 2 } } } integer: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err1.p1: incompatible integer bounds <1 and >2: // ./binary.cue:22:18 // ./binary.cue:22:13 } p2: (_|_){ // [eval] simplifyBinary.integer.err1.p2: incompatible integer bounds <1 and >2: // ./binary.cue:23:18 // ./binary.cue:23:13 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err2.p1: incompatible integer bounds <=1 and >2: // ./binary.cue:25:18 // ./binary.cue:25:13 } p2: (_|_){ // [eval] simplifyBinary.integer.err2.p2: incompatible integer bounds <=1 and >2: // ./binary.cue:26:19 // ./binary.cue:26:13 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err3.p1: incompatible integer bounds <2 and >=2: // ./binary.cue:28:19 // ./binary.cue:28:13 } p2: (_|_){ // [eval] simplifyBinary.integer.err3.p2: incompatible integer bounds <2 and >=2: // ./binary.cue:29:18 // ./binary.cue:29:13 } p3: (_|_){ // [eval] simplifyBinary.integer.err3.p3: incompatible integer bounds <=2 and >2: // ./binary.cue:30:18 // ./binary.cue:30:13 } p4: (_|_){ // [eval] simplifyBinary.integer.err3.p4: incompatible integer bounds <=2 and >2: // ./binary.cue:31:19 // ./binary.cue:31:13 } } err4: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err4.p1: incompatible integer bounds >1 and <2: // ./binary.cue:33:18 // ./binary.cue:33:13 } p2: (_|_){ // [eval] simplifyBinary.integer.err4.p2: incompatible integer bounds >1 and <2: // ./binary.cue:34:18 // ./binary.cue:34:13 } } ok1: (struct){ p1: (int){ &(>=2, <=3, int) } p2: (int){ &(>=2, <=3, int) } } ok2: (struct){ p1: (int){ 2 } p2: (int){ 2 } } ok3: (struct){ p1: (int){ 2 } p2: (int){ 3 } p3: (int){ 2 } p4: (int){ 3 } } } strings: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err1.p1: incompatible string bounds <"a" and >"b": // ./binarystring.cue:2:20 // ./binarystring.cue:2:13 } p2: (_|_){ // [eval] simplifyBinary.strings.err1.p2: incompatible string bounds <"a" and >"b": // ./binarystring.cue:3:20 // ./binarystring.cue:3:13 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err2.p1: incompatible string bounds <="a" and >"b": // ./binarystring.cue:5:20 // ./binarystring.cue:5:13 } p2: (_|_){ // [eval] simplifyBinary.strings.err2.p2: incompatible string bounds <="a" and >"b": // ./binarystring.cue:6:21 // ./binarystring.cue:6:13 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err3.p1: incompatible string bounds <"b" and >="b": // ./binarystring.cue:8:21 // ./binarystring.cue:8:13 } p2: (_|_){ // [eval] simplifyBinary.strings.err3.p2: incompatible string bounds <"b" and >="b": // ./binarystring.cue:9:20 // ./binarystring.cue:9:13 } p3: (_|_){ // [eval] simplifyBinary.strings.err3.p3: incompatible string bounds <="b" and >"b": // ./binarystring.cue:10:20 // ./binarystring.cue:10:13 } p4: (_|_){ // [eval] simplifyBinary.strings.err3.p4: incompatible string bounds <="b" and >"b": // ./binarystring.cue:11:21 // ./binarystring.cue:11:13 } } ok1: (struct){ p1: (string){ &(>"a", <"b") } p2: (string){ &(>"a", <"b") } } ok2: (struct){ p1: (string){ &(>"a", <="b") } p2: (string){ &(>"a", <="b") } p3: (string){ &(>="a", <"b") } p4: (string){ &(>="a", <"b") } } ok3: (struct){ p1: (string){ &(>="b", <="c") } p2: (string){ &(>="b", <="c") } } ok4: (struct){ p1: (string){ "b" } } } byte: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': // ./binarystring.cue:27:20 // ./binarystring.cue:27:13 } p2: (_|_){ // [eval] simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': // ./binarystring.cue:28:20 // ./binarystring.cue:28:13 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': // ./binarystring.cue:30:20 // ./binarystring.cue:30:13 } p2: (_|_){ // [eval] simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': // ./binarystring.cue:31:21 // ./binarystring.cue:31:13 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': // ./binarystring.cue:33:21 // ./binarystring.cue:33:13 } p2: (_|_){ // [eval] simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': // ./binarystring.cue:34:20 // ./binarystring.cue:34:13 } p3: (_|_){ // [eval] simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': // ./binarystring.cue:35:20 // ./binarystring.cue:35:13 } p4: (_|_){ // [eval] simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': // ./binarystring.cue:36:21 // ./binarystring.cue:36:13 } } ok1: (struct){ p1: (bytes){ &(>'a', <'b') } p2: (bytes){ &(>'a', <'b') } } ok2: (struct){ p1: (bytes){ &(>'a', <='b') } p2: (bytes){ &(>'a', <='b') } p3: (bytes){ &(>='a', <'b') } p4: (bytes){ &(>='a', <'b') } } ok3: (struct){ p1: (bytes){ &(>='b', <='c') } p2: (bytes){ &(>='b', <='c') } } ok4: (struct){ p1: (bytes){ 'b' } } } } x0: (int){ 5 } x1: (int){ 30 } b0: (number){ &(>0, <5) } b1: (int){ &(>0, <5, int) } b2: (int){ &(<5.5, int) } b3: (number){ <=5 } b4: (number){ >20 } b5: (number){ >=21 } b6: (int){ 6 } simplifyExpr: (_|_){ // [eval] less1: (number){ <3 } less2: (number){ <3 } less3: (number){ <3 } less4: (number){ <=3 } less5: (number){ number } less6: (number){ number } gtr1: (number){ >3 } gtr2: (number){ >3 } gtr3: (number){ >3 } gtr4: (number){ >=3 } gtr5: (number){ number } gtr6: (number){ number } lg1: (number){ number } lg2: (number){ number } lg3: (number){ number } lg4: (number){ number } gl1: (number){ number } gl2: (number){ number } gl3: (number){ number } gl4: (number){ number } ne1: (int){ 3 } ne2: (number){ >=3 } ne3: (number){ >3 } ne4: (number){ <=3 } ne5: (number){ <3 } s: (string){ string } n: (number){ number } i: (int){ int } f: (float){ float } b: (bytes){ bytes } basic1: (_|_){ // [incomplete] simplifyExpr.basic1: non-concrete value i for bound <: // ./in.cue:48:12 } basic2: (_|_){ // [incomplete] simplifyExpr.basic2: non-concrete value n for bound >: // ./in.cue:49:12 } basic3: (_|_){ // [incomplete] simplifyExpr.basic3: non-concrete value s for bound >=: // ./in.cue:50:13 } basic4: (_|_){ // [incomplete] simplifyExpr.basic4: non-concrete value f for bound <=: // ./in.cue:51:13 } basic5: (_|_){ // [incomplete] simplifyExpr.basic5: non-concrete value b for bound <=: // ./in.cue:52:13 } bne1: (_|_){ // [incomplete] simplifyExpr.bne1: non-concrete value s for bound !=: // ./in.cue:55:11 } bne2: (_|_){ // [incomplete] simplifyExpr.bne2: non-concrete value n for bound !=: // ./in.cue:56:11 } bne3: (_|_){ // [incomplete] simplifyExpr.bne3: non-concrete value n for bound !=: // ./in.cue:57:11 } bne4: (_|_){ // [incomplete] simplifyExpr.bne4: non-concrete value i for bound !=: // ./in.cue:58:11 } bne5: (_|_){ // [incomplete] simplifyExpr.bne5: non-concrete value b for bound !=: // ./in.cue:59:11 } e1: (_|_){ // [incomplete] simplifyExpr.e1: non-concrete value =~"foo" for bound <: // ./in.cue:61:8 } e2: (_|_){ // [eval] simplifyExpr.e2: cannot use null for bound >: // ./in.cue:62:8 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,110 +1,106 @@ Errors: -simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': - ./binarystring.cue:27:13 - ./binarystring.cue:27:20 -simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': - ./binarystring.cue:28:13 - ./binarystring.cue:28:20 -simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': - ./binarystring.cue:30:13 - ./binarystring.cue:30:20 -simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': - ./binarystring.cue:31:13 - ./binarystring.cue:31:21 -simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': - ./binarystring.cue:33:13 - ./binarystring.cue:33:21 -simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': - ./binarystring.cue:34:13 - ./binarystring.cue:34:20 -simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': - ./binarystring.cue:35:13 - ./binarystring.cue:35:20 -simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': - ./binarystring.cue:36:13 - ./binarystring.cue:36:21 simplifyBinary.float.err1.p1: incompatible number bounds <1 and >2: - ./binary.cue:2:13 ./binary.cue:2:18 + ./binary.cue:2:13 simplifyBinary.float.err1.p2: incompatible number bounds <1 and >2: - ./binary.cue:3:13 ./binary.cue:3:18 + ./binary.cue:3:13 simplifyBinary.float.err2.p1: incompatible number bounds <=1 and >2: - ./binary.cue:5:13 ./binary.cue:5:18 + ./binary.cue:5:13 simplifyBinary.float.err2.p2: incompatible number bounds <=1 and >2: - ./binary.cue:6:13 ./binary.cue:6:19 + ./binary.cue:6:13 simplifyBinary.float.err3.p1: incompatible number bounds <2 and >=2: - ./binary.cue:8:13 ./binary.cue:8:19 + ./binary.cue:8:13 simplifyBinary.float.err3.p2: incompatible number bounds <2 and >=2: - ./binary.cue:9:13 ./binary.cue:9:18 + ./binary.cue:9:13 simplifyBinary.float.err3.p3: incompatible number bounds <=2 and >2: - ./binary.cue:10:13 ./binary.cue:10:18 + ./binary.cue:10:13 simplifyBinary.float.err3.p4: incompatible number bounds <=2 and >2: - ./binary.cue:11:13 ./binary.cue:11:19 -simplifyBinary.integer.err1.p1: incompatible number bounds <1 and >2: - ./binary.cue:22:13 + ./binary.cue:11:13 +simplifyBinary.integer.err1.p1: incompatible integer bounds <1 and >2: ./binary.cue:22:18 -simplifyBinary.integer.err1.p2: incompatible number bounds <1 and >2: - ./binary.cue:23:13 + ./binary.cue:22:13 +simplifyBinary.integer.err1.p2: incompatible integer bounds <1 and >2: ./binary.cue:23:18 -simplifyBinary.integer.err2.p1: incompatible number bounds <=1 and >2: - ./binary.cue:25:13 + ./binary.cue:23:13 +simplifyBinary.integer.err2.p1: incompatible integer bounds <=1 and >2: ./binary.cue:25:18 -simplifyBinary.integer.err2.p2: incompatible number bounds <=1 and >2: - ./binary.cue:26:13 + ./binary.cue:25:13 +simplifyBinary.integer.err2.p2: incompatible integer bounds <=1 and >2: ./binary.cue:26:19 -simplifyBinary.integer.err3.p1: incompatible number bounds <2 and >=2: - ./binary.cue:28:13 + ./binary.cue:26:13 +simplifyBinary.integer.err3.p1: incompatible integer bounds <2 and >=2: ./binary.cue:28:19 -simplifyBinary.integer.err3.p2: incompatible number bounds <2 and >=2: - ./binary.cue:29:13 + ./binary.cue:28:13 +simplifyBinary.integer.err3.p2: incompatible integer bounds <2 and >=2: ./binary.cue:29:18 -simplifyBinary.integer.err3.p3: incompatible number bounds <=2 and >2: - ./binary.cue:30:13 + ./binary.cue:29:13 +simplifyBinary.integer.err3.p3: incompatible integer bounds <=2 and >2: ./binary.cue:30:18 -simplifyBinary.integer.err3.p4: incompatible number bounds <=2 and >2: - ./binary.cue:31:13 + ./binary.cue:30:13 +simplifyBinary.integer.err3.p4: incompatible integer bounds <=2 and >2: ./binary.cue:31:19 + ./binary.cue:31:13 simplifyBinary.integer.err4.p1: incompatible integer bounds >1 and <2: - ./binary.cue:21:8 - ./binary.cue:21:13 - ./binary.cue:33:13 ./binary.cue:33:18 + ./binary.cue:33:13 simplifyBinary.integer.err4.p2: incompatible integer bounds >1 and <2: - ./binary.cue:21:8 - ./binary.cue:21:13 - ./binary.cue:34:13 ./binary.cue:34:18 + ./binary.cue:34:13 simplifyBinary.strings.err1.p1: incompatible string bounds <"a" and >"b": - ./binarystring.cue:2:13 ./binarystring.cue:2:20 + ./binarystring.cue:2:13 simplifyBinary.strings.err1.p2: incompatible string bounds <"a" and >"b": - ./binarystring.cue:3:13 ./binarystring.cue:3:20 + ./binarystring.cue:3:13 simplifyBinary.strings.err2.p1: incompatible string bounds <="a" and >"b": - ./binarystring.cue:5:13 ./binarystring.cue:5:20 + ./binarystring.cue:5:13 simplifyBinary.strings.err2.p2: incompatible string bounds <="a" and >"b": - ./binarystring.cue:6:13 ./binarystring.cue:6:21 + ./binarystring.cue:6:13 simplifyBinary.strings.err3.p1: incompatible string bounds <"b" and >="b": - ./binarystring.cue:8:13 ./binarystring.cue:8:21 + ./binarystring.cue:8:13 simplifyBinary.strings.err3.p2: incompatible string bounds <"b" and >="b": - ./binarystring.cue:9:13 ./binarystring.cue:9:20 + ./binarystring.cue:9:13 simplifyBinary.strings.err3.p3: incompatible string bounds <="b" and >"b": - ./binarystring.cue:10:13 ./binarystring.cue:10:20 + ./binarystring.cue:10:13 simplifyBinary.strings.err3.p4: incompatible string bounds <="b" and >"b": - ./binarystring.cue:11:13 ./binarystring.cue:11:21 + ./binarystring.cue:11:13 +simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': + ./binarystring.cue:27:20 + ./binarystring.cue:27:13 +simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': + ./binarystring.cue:28:20 + ./binarystring.cue:28:13 +simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': + ./binarystring.cue:30:20 + ./binarystring.cue:30:13 +simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': + ./binarystring.cue:31:21 + ./binarystring.cue:31:13 +simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': + ./binarystring.cue:33:21 + ./binarystring.cue:33:13 +simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': + ./binarystring.cue:34:20 + ./binarystring.cue:34:13 +simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': + ./binarystring.cue:35:20 + ./binarystring.cue:35:13 +simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': + ./binarystring.cue:36:21 + ./binarystring.cue:36:13 simplifyExpr.e2: cannot use null for bound >: ./in.cue:62:8 @@ -119,13 +115,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err1.p1: incompatible number bounds <1 and >2: - // ./binary.cue:2:13 // ./binary.cue:2:18 + // ./binary.cue:2:13 } p2: (_|_){ // [eval] simplifyBinary.float.err1.p2: incompatible number bounds <1 and >2: - // ./binary.cue:3:13 // ./binary.cue:3:18 + // ./binary.cue:3:13 } } err2: (_|_){ @@ -132,13 +128,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err2.p1: incompatible number bounds <=1 and >2: - // ./binary.cue:5:13 // ./binary.cue:5:18 + // ./binary.cue:5:13 } p2: (_|_){ // [eval] simplifyBinary.float.err2.p2: incompatible number bounds <=1 and >2: - // ./binary.cue:6:13 // ./binary.cue:6:19 + // ./binary.cue:6:13 } } err3: (_|_){ @@ -145,23 +141,23 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err3.p1: incompatible number bounds <2 and >=2: - // ./binary.cue:8:13 // ./binary.cue:8:19 + // ./binary.cue:8:13 } p2: (_|_){ // [eval] simplifyBinary.float.err3.p2: incompatible number bounds <2 and >=2: - // ./binary.cue:9:13 // ./binary.cue:9:18 + // ./binary.cue:9:13 } p3: (_|_){ // [eval] simplifyBinary.float.err3.p3: incompatible number bounds <=2 and >2: - // ./binary.cue:10:13 // ./binary.cue:10:18 + // ./binary.cue:10:13 } p4: (_|_){ // [eval] simplifyBinary.float.err3.p4: incompatible number bounds <=2 and >2: - // ./binary.cue:11:13 // ./binary.cue:11:19 + // ./binary.cue:11:13 } } ok1: (struct){ @@ -178,50 +174,50 @@ err1: (_|_){ // [eval] p1: (_|_){ - // [eval] simplifyBinary.integer.err1.p1: incompatible number bounds <1 and >2: - // ./binary.cue:22:13 + // [eval] simplifyBinary.integer.err1.p1: incompatible integer bounds <1 and >2: // ./binary.cue:22:18 - } - p2: (_|_){ - // [eval] simplifyBinary.integer.err1.p2: incompatible number bounds <1 and >2: - // ./binary.cue:23:13 + // ./binary.cue:22:13 + } + p2: (_|_){ + // [eval] simplifyBinary.integer.err1.p2: incompatible integer bounds <1 and >2: // ./binary.cue:23:18 - } - } - err2: (_|_){ - // [eval] - p1: (_|_){ - // [eval] simplifyBinary.integer.err2.p1: incompatible number bounds <=1 and >2: - // ./binary.cue:25:13 + // ./binary.cue:23:13 + } + } + err2: (_|_){ + // [eval] + p1: (_|_){ + // [eval] simplifyBinary.integer.err2.p1: incompatible integer bounds <=1 and >2: // ./binary.cue:25:18 - } - p2: (_|_){ - // [eval] simplifyBinary.integer.err2.p2: incompatible number bounds <=1 and >2: - // ./binary.cue:26:13 + // ./binary.cue:25:13 + } + p2: (_|_){ + // [eval] simplifyBinary.integer.err2.p2: incompatible integer bounds <=1 and >2: // ./binary.cue:26:19 - } - } - err3: (_|_){ - // [eval] - p1: (_|_){ - // [eval] simplifyBinary.integer.err3.p1: incompatible number bounds <2 and >=2: - // ./binary.cue:28:13 + // ./binary.cue:26:13 + } + } + err3: (_|_){ + // [eval] + p1: (_|_){ + // [eval] simplifyBinary.integer.err3.p1: incompatible integer bounds <2 and >=2: // ./binary.cue:28:19 - } - p2: (_|_){ - // [eval] simplifyBinary.integer.err3.p2: incompatible number bounds <2 and >=2: - // ./binary.cue:29:13 + // ./binary.cue:28:13 + } + p2: (_|_){ + // [eval] simplifyBinary.integer.err3.p2: incompatible integer bounds <2 and >=2: // ./binary.cue:29:18 - } - p3: (_|_){ - // [eval] simplifyBinary.integer.err3.p3: incompatible number bounds <=2 and >2: - // ./binary.cue:30:13 + // ./binary.cue:29:13 + } + p3: (_|_){ + // [eval] simplifyBinary.integer.err3.p3: incompatible integer bounds <=2 and >2: // ./binary.cue:30:18 - } - p4: (_|_){ - // [eval] simplifyBinary.integer.err3.p4: incompatible number bounds <=2 and >2: - // ./binary.cue:31:13 + // ./binary.cue:30:13 + } + p4: (_|_){ + // [eval] simplifyBinary.integer.err3.p4: incompatible integer bounds <=2 and >2: // ./binary.cue:31:19 + // ./binary.cue:31:13 } } err4: (_|_){ @@ -228,17 +224,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err4.p1: incompatible integer bounds >1 and <2: - // ./binary.cue:21:8 - // ./binary.cue:21:13 - // ./binary.cue:33:13 // ./binary.cue:33:18 + // ./binary.cue:33:13 } p2: (_|_){ // [eval] simplifyBinary.integer.err4.p2: incompatible integer bounds >1 and <2: - // ./binary.cue:21:8 - // ./binary.cue:21:13 - // ./binary.cue:34:13 // ./binary.cue:34:18 + // ./binary.cue:34:13 } } ok1: (struct){ @@ -246,8 +238,8 @@ p2: (int){ &(>=2, <=3, int) } } ok2: (struct){ - p1: (number){ 2 } - p2: (number){ 2 } + p1: (int){ 2 } + p2: (int){ 2 } } ok3: (struct){ p1: (int){ 2 } @@ -262,13 +254,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err1.p1: incompatible string bounds <"a" and >"b": - // ./binarystring.cue:2:13 // ./binarystring.cue:2:20 + // ./binarystring.cue:2:13 } p2: (_|_){ // [eval] simplifyBinary.strings.err1.p2: incompatible string bounds <"a" and >"b": - // ./binarystring.cue:3:13 // ./binarystring.cue:3:20 + // ./binarystring.cue:3:13 } } err2: (_|_){ @@ -275,13 +267,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err2.p1: incompatible string bounds <="a" and >"b": - // ./binarystring.cue:5:13 // ./binarystring.cue:5:20 + // ./binarystring.cue:5:13 } p2: (_|_){ // [eval] simplifyBinary.strings.err2.p2: incompatible string bounds <="a" and >"b": - // ./binarystring.cue:6:13 // ./binarystring.cue:6:21 + // ./binarystring.cue:6:13 } } err3: (_|_){ @@ -288,23 +280,23 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err3.p1: incompatible string bounds <"b" and >="b": - // ./binarystring.cue:8:13 // ./binarystring.cue:8:21 + // ./binarystring.cue:8:13 } p2: (_|_){ // [eval] simplifyBinary.strings.err3.p2: incompatible string bounds <"b" and >="b": - // ./binarystring.cue:9:13 // ./binarystring.cue:9:20 + // ./binarystring.cue:9:13 } p3: (_|_){ // [eval] simplifyBinary.strings.err3.p3: incompatible string bounds <="b" and >"b": - // ./binarystring.cue:10:13 // ./binarystring.cue:10:20 + // ./binarystring.cue:10:13 } p4: (_|_){ // [eval] simplifyBinary.strings.err3.p4: incompatible string bounds <="b" and >"b": - // ./binarystring.cue:11:13 // ./binarystring.cue:11:21 + // ./binarystring.cue:11:13 } } ok1: (struct){ @@ -331,13 +323,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': - // ./binarystring.cue:27:13 // ./binarystring.cue:27:20 + // ./binarystring.cue:27:13 } p2: (_|_){ // [eval] simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': - // ./binarystring.cue:28:13 // ./binarystring.cue:28:20 + // ./binarystring.cue:28:13 } } err2: (_|_){ @@ -344,13 +336,13 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': - // ./binarystring.cue:30:13 // ./binarystring.cue:30:20 + // ./binarystring.cue:30:13 } p2: (_|_){ // [eval] simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': - // ./binarystring.cue:31:13 // ./binarystring.cue:31:21 + // ./binarystring.cue:31:13 } } err3: (_|_){ @@ -357,23 +349,23 @@ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': - // ./binarystring.cue:33:13 // ./binarystring.cue:33:21 + // ./binarystring.cue:33:13 } p2: (_|_){ // [eval] simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': - // ./binarystring.cue:34:13 // ./binarystring.cue:34:20 + // ./binarystring.cue:34:13 } p3: (_|_){ // [eval] simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': - // ./binarystring.cue:35:13 // ./binarystring.cue:35:20 + // ./binarystring.cue:35:13 } p4: (_|_){ // [eval] simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': - // ./binarystring.cue:36:13 // ./binarystring.cue:36:21 + // ./binarystring.cue:36:13 } } ok1: (struct){ -- diff/explanation -- simplifyBinary.integer.ok2.*: v3 indicates correct type. -- out/eval -- Errors: simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': ./binarystring.cue:27:13 ./binarystring.cue:27:20 simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': ./binarystring.cue:28:13 ./binarystring.cue:28:20 simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': ./binarystring.cue:30:13 ./binarystring.cue:30:20 simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': ./binarystring.cue:31:13 ./binarystring.cue:31:21 simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': ./binarystring.cue:33:13 ./binarystring.cue:33:21 simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': ./binarystring.cue:34:13 ./binarystring.cue:34:20 simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': ./binarystring.cue:35:13 ./binarystring.cue:35:20 simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': ./binarystring.cue:36:13 ./binarystring.cue:36:21 simplifyBinary.float.err1.p1: incompatible number bounds <1 and >2: ./binary.cue:2:13 ./binary.cue:2:18 simplifyBinary.float.err1.p2: incompatible number bounds <1 and >2: ./binary.cue:3:13 ./binary.cue:3:18 simplifyBinary.float.err2.p1: incompatible number bounds <=1 and >2: ./binary.cue:5:13 ./binary.cue:5:18 simplifyBinary.float.err2.p2: incompatible number bounds <=1 and >2: ./binary.cue:6:13 ./binary.cue:6:19 simplifyBinary.float.err3.p1: incompatible number bounds <2 and >=2: ./binary.cue:8:13 ./binary.cue:8:19 simplifyBinary.float.err3.p2: incompatible number bounds <2 and >=2: ./binary.cue:9:13 ./binary.cue:9:18 simplifyBinary.float.err3.p3: incompatible number bounds <=2 and >2: ./binary.cue:10:13 ./binary.cue:10:18 simplifyBinary.float.err3.p4: incompatible number bounds <=2 and >2: ./binary.cue:11:13 ./binary.cue:11:19 simplifyBinary.integer.err1.p1: incompatible number bounds <1 and >2: ./binary.cue:22:13 ./binary.cue:22:18 simplifyBinary.integer.err1.p2: incompatible number bounds <1 and >2: ./binary.cue:23:13 ./binary.cue:23:18 simplifyBinary.integer.err2.p1: incompatible number bounds <=1 and >2: ./binary.cue:25:13 ./binary.cue:25:18 simplifyBinary.integer.err2.p2: incompatible number bounds <=1 and >2: ./binary.cue:26:13 ./binary.cue:26:19 simplifyBinary.integer.err3.p1: incompatible number bounds <2 and >=2: ./binary.cue:28:13 ./binary.cue:28:19 simplifyBinary.integer.err3.p2: incompatible number bounds <2 and >=2: ./binary.cue:29:13 ./binary.cue:29:18 simplifyBinary.integer.err3.p3: incompatible number bounds <=2 and >2: ./binary.cue:30:13 ./binary.cue:30:18 simplifyBinary.integer.err3.p4: incompatible number bounds <=2 and >2: ./binary.cue:31:13 ./binary.cue:31:19 simplifyBinary.integer.err4.p1: incompatible integer bounds >1 and <2: ./binary.cue:21:8 ./binary.cue:21:13 ./binary.cue:33:13 ./binary.cue:33:18 simplifyBinary.integer.err4.p2: incompatible integer bounds >1 and <2: ./binary.cue:21:8 ./binary.cue:21:13 ./binary.cue:34:13 ./binary.cue:34:18 simplifyBinary.strings.err1.p1: incompatible string bounds <"a" and >"b": ./binarystring.cue:2:13 ./binarystring.cue:2:20 simplifyBinary.strings.err1.p2: incompatible string bounds <"a" and >"b": ./binarystring.cue:3:13 ./binarystring.cue:3:20 simplifyBinary.strings.err2.p1: incompatible string bounds <="a" and >"b": ./binarystring.cue:5:13 ./binarystring.cue:5:20 simplifyBinary.strings.err2.p2: incompatible string bounds <="a" and >"b": ./binarystring.cue:6:13 ./binarystring.cue:6:21 simplifyBinary.strings.err3.p1: incompatible string bounds <"b" and >="b": ./binarystring.cue:8:13 ./binarystring.cue:8:21 simplifyBinary.strings.err3.p2: incompatible string bounds <"b" and >="b": ./binarystring.cue:9:13 ./binarystring.cue:9:20 simplifyBinary.strings.err3.p3: incompatible string bounds <="b" and >"b": ./binarystring.cue:10:13 ./binarystring.cue:10:20 simplifyBinary.strings.err3.p4: incompatible string bounds <="b" and >"b": ./binarystring.cue:11:13 ./binarystring.cue:11:21 simplifyExpr.e2: cannot use null for bound >: ./in.cue:62:8 Result: (_|_){ // [eval] simplifyBinary: (_|_){ // [eval] float: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err1.p1: incompatible number bounds <1 and >2: // ./binary.cue:2:13 // ./binary.cue:2:18 } p2: (_|_){ // [eval] simplifyBinary.float.err1.p2: incompatible number bounds <1 and >2: // ./binary.cue:3:13 // ./binary.cue:3:18 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err2.p1: incompatible number bounds <=1 and >2: // ./binary.cue:5:13 // ./binary.cue:5:18 } p2: (_|_){ // [eval] simplifyBinary.float.err2.p2: incompatible number bounds <=1 and >2: // ./binary.cue:6:13 // ./binary.cue:6:19 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.float.err3.p1: incompatible number bounds <2 and >=2: // ./binary.cue:8:13 // ./binary.cue:8:19 } p2: (_|_){ // [eval] simplifyBinary.float.err3.p2: incompatible number bounds <2 and >=2: // ./binary.cue:9:13 // ./binary.cue:9:18 } p3: (_|_){ // [eval] simplifyBinary.float.err3.p3: incompatible number bounds <=2 and >2: // ./binary.cue:10:13 // ./binary.cue:10:18 } p4: (_|_){ // [eval] simplifyBinary.float.err3.p4: incompatible number bounds <=2 and >2: // ./binary.cue:11:13 // ./binary.cue:11:19 } } ok1: (struct){ p1: (number){ &(>1, <2) } p2: (number){ &(>1, <2) } } ok2: (struct){ p1: (number){ 2 } p2: (number){ 2 } } } integer: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err1.p1: incompatible number bounds <1 and >2: // ./binary.cue:22:13 // ./binary.cue:22:18 } p2: (_|_){ // [eval] simplifyBinary.integer.err1.p2: incompatible number bounds <1 and >2: // ./binary.cue:23:13 // ./binary.cue:23:18 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err2.p1: incompatible number bounds <=1 and >2: // ./binary.cue:25:13 // ./binary.cue:25:18 } p2: (_|_){ // [eval] simplifyBinary.integer.err2.p2: incompatible number bounds <=1 and >2: // ./binary.cue:26:13 // ./binary.cue:26:19 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err3.p1: incompatible number bounds <2 and >=2: // ./binary.cue:28:13 // ./binary.cue:28:19 } p2: (_|_){ // [eval] simplifyBinary.integer.err3.p2: incompatible number bounds <2 and >=2: // ./binary.cue:29:13 // ./binary.cue:29:18 } p3: (_|_){ // [eval] simplifyBinary.integer.err3.p3: incompatible number bounds <=2 and >2: // ./binary.cue:30:13 // ./binary.cue:30:18 } p4: (_|_){ // [eval] simplifyBinary.integer.err3.p4: incompatible number bounds <=2 and >2: // ./binary.cue:31:13 // ./binary.cue:31:19 } } err4: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.integer.err4.p1: incompatible integer bounds >1 and <2: // ./binary.cue:21:8 // ./binary.cue:21:13 // ./binary.cue:33:13 // ./binary.cue:33:18 } p2: (_|_){ // [eval] simplifyBinary.integer.err4.p2: incompatible integer bounds >1 and <2: // ./binary.cue:21:8 // ./binary.cue:21:13 // ./binary.cue:34:13 // ./binary.cue:34:18 } } ok1: (struct){ p1: (int){ &(>=2, <=3, int) } p2: (int){ &(>=2, <=3, int) } } ok2: (struct){ p1: (number){ 2 } p2: (number){ 2 } } ok3: (struct){ p1: (int){ 2 } p2: (int){ 3 } p3: (int){ 2 } p4: (int){ 3 } } } strings: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err1.p1: incompatible string bounds <"a" and >"b": // ./binarystring.cue:2:13 // ./binarystring.cue:2:20 } p2: (_|_){ // [eval] simplifyBinary.strings.err1.p2: incompatible string bounds <"a" and >"b": // ./binarystring.cue:3:13 // ./binarystring.cue:3:20 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err2.p1: incompatible string bounds <="a" and >"b": // ./binarystring.cue:5:13 // ./binarystring.cue:5:20 } p2: (_|_){ // [eval] simplifyBinary.strings.err2.p2: incompatible string bounds <="a" and >"b": // ./binarystring.cue:6:13 // ./binarystring.cue:6:21 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.strings.err3.p1: incompatible string bounds <"b" and >="b": // ./binarystring.cue:8:13 // ./binarystring.cue:8:21 } p2: (_|_){ // [eval] simplifyBinary.strings.err3.p2: incompatible string bounds <"b" and >="b": // ./binarystring.cue:9:13 // ./binarystring.cue:9:20 } p3: (_|_){ // [eval] simplifyBinary.strings.err3.p3: incompatible string bounds <="b" and >"b": // ./binarystring.cue:10:13 // ./binarystring.cue:10:20 } p4: (_|_){ // [eval] simplifyBinary.strings.err3.p4: incompatible string bounds <="b" and >"b": // ./binarystring.cue:11:13 // ./binarystring.cue:11:21 } } ok1: (struct){ p1: (string){ &(>"a", <"b") } p2: (string){ &(>"a", <"b") } } ok2: (struct){ p1: (string){ &(>"a", <="b") } p2: (string){ &(>"a", <="b") } p3: (string){ &(>="a", <"b") } p4: (string){ &(>="a", <"b") } } ok3: (struct){ p1: (string){ &(>="b", <="c") } p2: (string){ &(>="b", <="c") } } ok4: (struct){ p1: (string){ "b" } } } byte: (_|_){ // [eval] err1: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err1.p1: incompatible bytes bounds <'a' and >'b': // ./binarystring.cue:27:13 // ./binarystring.cue:27:20 } p2: (_|_){ // [eval] simplifyBinary.byte.err1.p2: incompatible bytes bounds <'a' and >'b': // ./binarystring.cue:28:13 // ./binarystring.cue:28:20 } } err2: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err2.p1: incompatible bytes bounds <='a' and >'b': // ./binarystring.cue:30:13 // ./binarystring.cue:30:20 } p2: (_|_){ // [eval] simplifyBinary.byte.err2.p2: incompatible bytes bounds <='a' and >'b': // ./binarystring.cue:31:13 // ./binarystring.cue:31:21 } } err3: (_|_){ // [eval] p1: (_|_){ // [eval] simplifyBinary.byte.err3.p1: incompatible bytes bounds <'b' and >='b': // ./binarystring.cue:33:13 // ./binarystring.cue:33:21 } p2: (_|_){ // [eval] simplifyBinary.byte.err3.p2: incompatible bytes bounds <'b' and >='b': // ./binarystring.cue:34:13 // ./binarystring.cue:34:20 } p3: (_|_){ // [eval] simplifyBinary.byte.err3.p3: incompatible bytes bounds <='b' and >'b': // ./binarystring.cue:35:13 // ./binarystring.cue:35:20 } p4: (_|_){ // [eval] simplifyBinary.byte.err3.p4: incompatible bytes bounds <='b' and >'b': // ./binarystring.cue:36:13 // ./binarystring.cue:36:21 } } ok1: (struct){ p1: (bytes){ &(>'a', <'b') } p2: (bytes){ &(>'a', <'b') } } ok2: (struct){ p1: (bytes){ &(>'a', <='b') } p2: (bytes){ &(>'a', <='b') } p3: (bytes){ &(>='a', <'b') } p4: (bytes){ &(>='a', <'b') } } ok3: (struct){ p1: (bytes){ &(>='b', <='c') } p2: (bytes){ &(>='b', <='c') } } ok4: (struct){ p1: (bytes){ 'b' } } } } x0: (int){ 5 } x1: (int){ 30 } b0: (number){ &(>0, <5) } b1: (int){ &(>0, <5, int) } b2: (int){ &(<5.5, int) } b3: (number){ <=5 } b4: (number){ >20 } b5: (number){ >=21 } b6: (int){ 6 } simplifyExpr: (_|_){ // [eval] less1: (number){ <3 } less2: (number){ <3 } less3: (number){ <3 } less4: (number){ <=3 } less5: (number){ number } less6: (number){ number } gtr1: (number){ >3 } gtr2: (number){ >3 } gtr3: (number){ >3 } gtr4: (number){ >=3 } gtr5: (number){ number } gtr6: (number){ number } lg1: (number){ number } lg2: (number){ number } lg3: (number){ number } lg4: (number){ number } gl1: (number){ number } gl2: (number){ number } gl3: (number){ number } gl4: (number){ number } ne1: (int){ 3 } ne2: (number){ >=3 } ne3: (number){ >3 } ne4: (number){ <=3 } ne5: (number){ <3 } s: (string){ string } n: (number){ number } i: (int){ int } f: (float){ float } b: (bytes){ bytes } basic1: (_|_){ // [incomplete] simplifyExpr.basic1: non-concrete value i for bound <: // ./in.cue:48:12 } basic2: (_|_){ // [incomplete] simplifyExpr.basic2: non-concrete value n for bound >: // ./in.cue:49:12 } basic3: (_|_){ // [incomplete] simplifyExpr.basic3: non-concrete value s for bound >=: // ./in.cue:50:13 } basic4: (_|_){ // [incomplete] simplifyExpr.basic4: non-concrete value f for bound <=: // ./in.cue:51:13 } basic5: (_|_){ // [incomplete] simplifyExpr.basic5: non-concrete value b for bound <=: // ./in.cue:52:13 } bne1: (_|_){ // [incomplete] simplifyExpr.bne1: non-concrete value s for bound !=: // ./in.cue:55:11 } bne2: (_|_){ // [incomplete] simplifyExpr.bne2: non-concrete value n for bound !=: // ./in.cue:56:11 } bne3: (_|_){ // [incomplete] simplifyExpr.bne3: non-concrete value n for bound !=: // ./in.cue:57:11 } bne4: (_|_){ // [incomplete] simplifyExpr.bne4: non-concrete value i for bound !=: // ./in.cue:58:11 } bne5: (_|_){ // [incomplete] simplifyExpr.bne5: non-concrete value b for bound !=: // ./in.cue:59:11 } e1: (_|_){ // [incomplete] simplifyExpr.e1: non-concrete value =~"foo" for bound <: // ./in.cue:61:8 } e2: (_|_){ // [eval] simplifyExpr.e2: cannot use null for bound >: // ./in.cue:62:8 } } } -- out/compile -- --- binary.cue { simplifyBinary: { float: { err1: { p1: (<1 & >2) } err1: { p2: (>2 & <1) } err2: { p1: (>2 & <=1) } err2: { p2: (<=1 & >2) } err3: { p1: (>=2 & <2) } err3: { p2: (<2 & >=2) } err3: { p3: (>2 & <=2) } err3: { p4: (<=2 & >2) } ok1: { p1: (>1 & <2) } ok1: { p2: (<2 & >1) } ok2: { p1: (>=2 & <=2) } ok2: { p2: (<=2 & >=2) } } } simplifyBinary: { integer: { [_]: { [_]: int } err1: { p1: (<1 & >2) } err1: { p2: (>2 & <1) } err2: { p1: (>2 & <=1) } err2: { p2: (<=1 & >2) } err3: { p1: (>=2 & <2) } err3: { p2: (<2 & >=2) } err3: { p3: (>2 & <=2) } err3: { p4: (<=2 & >2) } err4: { p1: (>1 & <2) } err4: { p2: (<2 & >1) } ok1: { p1: (>=2 & <=3) } ok1: { p2: (<=3 & >=2) } ok2: { p1: (>=2 & <=2) } ok2: { p2: (<=2 & >=2) } ok3: { p1: (>=2 & <3) } ok3: { p2: (>2 & <=3) } ok3: { p3: (<3 & >=2) } ok3: { p4: (<=3 & >2) } } } } --- binarystring.cue { simplifyBinary: { strings: { err1: { p1: (<"a" & >"b") } err1: { p2: (>"b" & <"a") } err2: { p1: (>"b" & <="a") } err2: { p2: (<="a" & >"b") } err3: { p1: (>="b" & <"b") } err3: { p2: (<"b" & >="b") } err3: { p3: (>"b" & <="b") } err3: { p4: (<="b" & >"b") } ok1: { p1: (>"a" & <"b") } ok1: { p2: (<"b" & >"a") } ok2: { p1: (>"a" & <="b") } ok2: { p2: (<="b" & >"a") } ok2: { p3: (>="a" & <"b") } ok2: { p4: (<"b" & >="a") } ok3: { p1: (>="b" & <="c") } ok3: { p2: (<="c" & >="b") } ok4: { p1: (>="b" & <="b") } } } simplifyBinary: { byte: { err1: { p1: (<'a' & >'b') } err1: { p2: (>'b' & <'a') } err2: { p1: (>'b' & <='a') } err2: { p2: (<='a' & >'b') } err3: { p1: (>='b' & <'b') } err3: { p2: (<'b' & >='b') } err3: { p3: (>'b' & <='b') } err3: { p4: (<='b' & >'b') } ok1: { p1: (>'a' & <'b') } ok1: { p2: (<'b' & >'a') } ok2: { p1: (>'a' & <='b') } ok2: { p2: (<='b' & >'a') } ok2: { p3: (>='a' & <'b') } ok2: { p4: (<'b' & >='a') } ok3: { p1: (>='b' & <='c') } ok3: { p2: (<='c' & >='b') } ok4: { p1: (>='b' & <='b') } } } } --- in.cue { x0: 5 x1: (〈0;b5〉 & 30) b0: (<〈0;x0〉 & >0) b1: (〈0;b0〉 & int) b2: (int & <5.5) b3: (<10 & <=5) b4: (>=20 & >20) b5: (>=21 & >20) b6: ((int & >5) & <=6) simplifyExpr: { less1: <<3 less2: <<=3 less3: <=<3 less4: <=<=3 less5: >3 gtr2: >>=3 gtr3: >=>3 gtr4: >=>=3 gtr5: >!=3 gtr6: >=!=3 lg1: <>3 lg2: <>=3 lg3: <=>3 lg4: <=>=3 gl1: ><3 gl2: ><=3 gl3: >=<3 gl4: >=<=3 ne1: !=!=3 ne2: !=<3 ne3: !=<=3 ne4: !=>3 ne5: !=>=3 s: string n: number i: int f: float b: bytes basic1: <〈0;i〉 basic2: >〈0;n〉 basic3: >=〈0;s〉 basic4: <=〈0;f〉 basic5: <=〈0;b〉 bne1: !=〈0;s〉 bne2: !=〈0;n〉 bne3: !=〈0;n〉 bne4: !=〈0;i〉 bne5: !=〈0;b〉 e1: <=~"foo" e2: >null } } cue-lang-cue-db9cc73/cue/testdata/eval/bulk.txtar000066400000000000000000000734321474664451600220460ustar00rootroot00000000000000-- in.cue -- a: { foo: a: 1 [X = =~"foo"]: { b: 1 name: X } } d: a & { "foobar": { c: 2 } } t1: { #a: { [>"e" & <"z"]: int } b: #a & {f: 4} c: #a & {z: 4} } t2: { #a: { ["x" | "y"]: int } b: #a & {x: 4} c: #a & {z: 4} } -- issue2109.cue -- // Detect cycle: // The pattern constraint of FlagsURLS is applied to countries (because // FlagsURLs is embedded. But the pattern constraint itself refers to // countries. So countries -> or(countries) -> countries. // // Theoretically, or(countries) can be resolved without a cycle. And then we // could see it does not apply to countries. For now we stick with this // approach understanding that it is easier to relax later. patternCycle: issue2109: p1: { countries: ["US", "GB", "AU"] FlagsURLs: {[or(countries)]: string} FlagsURLs } patternCycle: issue2109: p2: { FlagsURLs: {[or(countries)]: string} FlagsURLs countries: ["US", "GB", "AU"] } patternCycle: issue2109: p3: { FlagsURLs FlagsURLs: {[or(countries)]: string} countries: ["US", "GB", "AU"] } patternCycle: t1: p1: { countries: "US" | "GB" | "AU" FlagsURLs: {[countries]: string} FlagsURLs } patternCycle: t1: p2: { FlagsURLs countries: "US" | "GB" | "AU" FlagsURLs: {[countries]: string} } patternCycle: t1: p3: { FlagsURLs FlagsURLs: {[countries]: string} countries: "US" | "GB" | "AU" } -- intpattern.cue -- issue3670: { #X: [int]: string a: #X a: "not_int": "c" } dual: { _ // As long as it is undecided whether this is a struct or list, this should // not be a conflict. Note that the spec does not allow int patterns, but // both v2 and v3 allow it, and we soon will, so it seems gratuitous to // break it now. [string]: _ [int]: _ } -- multi.cue -- // Ensure that if the same pattern is added multiple times in different // contexts, it is added to all contexts to preserve closedness information. issue3638: full: { routes: default: {} routes: [string]: spec: [{ refs: [{"default"}] }] #Fields: { input: _ output: [for x in input { x }] ... } #Kubernetes: { #Fields & { Routes: route: [_]: spec!: HTTPROUTESPEC.#x } #Fields // Commenting out this line also fixes evalv3. Routes: _ input: res1: Routes } let HTTPROUTESPEC = { #x: [...{ refs: [...{string}] }] | *[{ other: [] }] } // Order dependent! Breaks if the lines below are moved to the top of the file. entrypoint: used.output used: #Kubernetes & { Routes: route: routes } } issue3638: reduced: { input: k1: [string]: a: 1 input: k1: foo: #x out: { for x in input { x } for x in input { x } } #x: { a: int } | *{ b: 2 } } // We expect that changing the pattern constraint into a field should give // not materially change the outcome. issue3638: compare: { input: k1: foo: a: 1 input: k1: foo: #x out: { for x in input { x } for x in input { x } } #x: { a: int } | *{ b: 2 } } -- out/eval/stats -- Leaks: 4 Freed: 269 Reused: 250 Allocs: 23 Retain: 30 Unifications: 214 Conjuncts: 639 Disjuncts: 297 -- out/evalalpha -- Errors: t1.c.z: field not allowed: ./in.cue:16:18 ./in.cue:19:11 t2.c.z: field not allowed: ./in.cue:24:16 ./in.cue:27:11 issue3670.a.not_int: field not allowed: ./intpattern.cue:2:13 ./intpattern.cue:4:5 Result: (_|_){ // [eval] a: (struct){ foo: (struct){ a: (int){ 1 } b: (int){ 1 } name: (string){ "foo" } } } d: (struct){ foobar: (struct){ c: (int){ 2 } b: (int){ 1 } name: (string){ "foobar" } } foo: (struct){ a: (int){ 1 } b: (int){ 1 } name: (string){ "foo" } } } t1: (_|_){ // [eval] #a: (#struct){ } b: (#struct){ f: (int){ 4 } } c: (_|_){ // [eval] z: (_|_){ // [eval] t1.c.z: field not allowed: // ./in.cue:16:18 // ./in.cue:19:11 } } } t2: (_|_){ // [eval] #a: (#struct){ } b: (#struct){ x: (int){ 4 } } c: (_|_){ // [eval] z: (_|_){ // [eval] t2.c.z: field not allowed: // ./in.cue:24:16 // ./in.cue:27:11 } } } issue3670: (_|_){ // [eval] #X: (#struct){ } a: (_|_){ // [eval] not_int: (_|_){ // [eval] issue3670.a.not_int: field not allowed: // ./intpattern.cue:2:13 // ./intpattern.cue:4:5 } } } dual: (_){ _ } patternCycle: (struct){ issue2109: (struct){ p1: (struct){ countries: (#list){ 0: (string){ "US" } 1: (string){ "GB" } 2: (string){ "AU" } } FlagsURLs: (struct){ } } p2: (struct){ FlagsURLs: (struct){ } countries: (#list){ 0: (string){ "US" } 1: (string){ "GB" } 2: (string){ "AU" } } } p3: (struct){ FlagsURLs: (struct){ } countries: (#list){ 0: (string){ "US" } 1: (string){ "GB" } 2: (string){ "AU" } } } } t1: (struct){ p1: (struct){ countries: (string){ |((string){ "US" }, (string){ "GB" }, (string){ "AU" }) } FlagsURLs: (struct){ } } p2: (struct){ countries: (string){ |((string){ "US" }, (string){ "GB" }, (string){ "AU" }) } FlagsURLs: (struct){ } } p3: (struct){ FlagsURLs: (struct){ } countries: (string){ |((string){ "US" }, (string){ "GB" }, (string){ "AU" }) } } } } issue3638: (struct){ full: (struct){ routes: (struct){ default: (struct){ spec: (#list){ 0: (struct){ refs: (#list){ 0: (string){ "default" } } } } } } #Fields: (#struct){ input: (_){ _ } output: (_|_){ // [incomplete] issue3638.full.#Fields.output: cannot range over input (incomplete type _): // ./multi.cue:10:21 } } #Kubernetes: (#struct){ Routes: (#struct){ route: (#struct){ } } input: (#struct){ res1: ~(issue3638.full.#Kubernetes.Routes) } output: (#list){ 0: (#struct){ route: (#struct){ } } } } let HTTPROUTESPEC#1 = (struct){ #x: (#list){ |(*(#list){ 0: (#struct){ other: (#list){ } } }, (list){ }) } } entrypoint: ~(issue3638.full.used.output) used: (#struct){ Routes: (#struct){ route: (#struct){ default: (#struct){ spec: (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } } } } } input: (#struct){ res1: (#struct){ route: (#struct){ default: (#struct){ spec: (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } } } } } } output: (#list){ 0: (#struct){ route: (#struct){ default: (#struct){ spec: (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } } } } } } } } reduced: (struct){ input: (struct){ k1: (struct){ foo: (#struct){ a: (int){ 1 } } } } out: (struct){ foo: (#struct){ a: (int){ 1 } } } #x: (#struct){ |(*(#struct){ b: (int){ 2 } }, (#struct){ a: (int){ int } }) } } compare: (struct){ input: (struct){ k1: (struct){ foo: (#struct){ a: (int){ 1 } } } } out: (struct){ foo: (#struct){ a: (int){ 1 } } } #x: (#struct){ |(*(#struct){ b: (int){ 2 } }, (#struct){ a: (int){ int } }) } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,34 +1,13 @@ Errors: -issue3670.a.not_int: field not allowed: - ./intpattern.cue:2:6 - ./intpattern.cue:3:5 - ./intpattern.cue:4:5 t1.c.z: field not allowed: - ./in.cue:15:6 - ./in.cue:19:5 + ./in.cue:16:18 ./in.cue:19:11 t2.c.z: field not allowed: - ./in.cue:23:6 - ./in.cue:27:5 + ./in.cue:24:16 ./in.cue:27:11 -patternCycle.issue2109.p1.countries: cyclic pattern constraint: - ./issue2109.cue:11:15 - ./issue2109.cue:10:13 -patternCycle.issue2109.p2.countries: cyclic pattern constraint: - ./issue2109.cue:15:15 - ./issue2109.cue:17:13 -patternCycle.issue2109.p3.countries: cyclic pattern constraint: - ./issue2109.cue:21:15 - ./issue2109.cue:22:13 -patternCycle.t1.p1.countries: cyclic pattern constraint: - ./issue2109.cue:27:15 - ./issue2109.cue:26:13 -patternCycle.t1.p2.countries: cyclic pattern constraint: - ./issue2109.cue:33:15 - ./issue2109.cue:32:13 -patternCycle.t1.p3.countries: cyclic pattern constraint: - ./issue2109.cue:37:15 - ./issue2109.cue:38:13 +issue3670.a.not_int: field not allowed: + ./intpattern.cue:2:13 + ./intpattern.cue:4:5 Result: (_|_){ @@ -41,16 +20,16 @@ } } d: (struct){ - foo: (struct){ - a: (int){ 1 } - b: (int){ 1 } - name: (string){ "foo" } - } foobar: (struct){ c: (int){ 2 } b: (int){ 1 } name: (string){ "foobar" } } + foo: (struct){ + a: (int){ 1 } + b: (int){ 1 } + name: (string){ "foo" } + } } t1: (_|_){ // [eval] @@ -63,8 +42,7 @@ // [eval] z: (_|_){ // [eval] t1.c.z: field not allowed: - // ./in.cue:15:6 - // ./in.cue:19:5 + // ./in.cue:16:18 // ./in.cue:19:11 } } @@ -80,8 +58,7 @@ // [eval] z: (_|_){ // [eval] t2.c.z: field not allowed: - // ./in.cue:23:6 - // ./in.cue:27:5 + // ./in.cue:24:16 // ./in.cue:27:11 } } @@ -94,94 +71,57 @@ // [eval] not_int: (_|_){ // [eval] issue3670.a.not_int: field not allowed: - // ./intpattern.cue:2:6 - // ./intpattern.cue:3:5 + // ./intpattern.cue:2:13 // ./intpattern.cue:4:5 } } } dual: (_){ _ } - patternCycle: (_|_){ - // [eval] - issue2109: (_|_){ - // [eval] - p1: (_|_){ - // [eval] - countries: (_|_){ - // [eval] patternCycle.issue2109.p1.countries: cyclic pattern constraint: - // ./issue2109.cue:11:15 - // ./issue2109.cue:10:13 - 0: (string){ "US" } - 1: (string){ "GB" } - 2: (string){ "AU" } - } - FlagsURLs: (struct){ - } - } - p2: (_|_){ - // [eval] - FlagsURLs: (struct){ - } - countries: (_|_){ - // [eval] patternCycle.issue2109.p2.countries: cyclic pattern constraint: - // ./issue2109.cue:15:15 - // ./issue2109.cue:17:13 - 0: (_|_){// "US" - } - 1: (_|_){// "GB" - } - 2: (_|_){// "AU" - } - } - } - p3: (_|_){ - // [eval] - FlagsURLs: (struct){ - } - countries: (_|_){ - // [eval] patternCycle.issue2109.p3.countries: cyclic pattern constraint: - // ./issue2109.cue:21:15 - // ./issue2109.cue:22:13 - 0: (_|_){// "US" - } - 1: (_|_){// "GB" - } - 2: (_|_){// "AU" - } - } - } - } - t1: (_|_){ - // [eval] - p1: (_|_){ - // [eval] - countries: (_|_){ - // [eval] patternCycle.t1.p1.countries: cyclic pattern constraint: - // ./issue2109.cue:27:15 - // ./issue2109.cue:26:13 - } - FlagsURLs: (struct){ - } - } - p2: (_|_){ - // [eval] - countries: (_|_){ - // [eval] patternCycle.t1.p2.countries: cyclic pattern constraint: - // ./issue2109.cue:33:15 - // ./issue2109.cue:32:13 - } - FlagsURLs: (struct){ - } - } - p3: (_|_){ - // [eval] - FlagsURLs: (struct){ - } - countries: (_|_){ - // [eval] patternCycle.t1.p3.countries: cyclic pattern constraint: - // ./issue2109.cue:37:15 - // ./issue2109.cue:38:13 - } + patternCycle: (struct){ + issue2109: (struct){ + p1: (struct){ + countries: (#list){ + 0: (string){ "US" } + 1: (string){ "GB" } + 2: (string){ "AU" } + } + FlagsURLs: (struct){ + } + } + p2: (struct){ + FlagsURLs: (struct){ + } + countries: (#list){ + 0: (string){ "US" } + 1: (string){ "GB" } + 2: (string){ "AU" } + } + } + p3: (struct){ + FlagsURLs: (struct){ + } + countries: (#list){ + 0: (string){ "US" } + 1: (string){ "GB" } + 2: (string){ "AU" } + } + } + } + t1: (struct){ + p1: (struct){ + countries: (string){ |((string){ "US" }, (string){ "GB" }, (string){ "AU" }) } + FlagsURLs: (struct){ + } + } + p2: (struct){ + countries: (string){ |((string){ "US" }, (string){ "GB" }, (string){ "AU" }) } + FlagsURLs: (struct){ + } + } + p3: (struct){ + FlagsURLs: (struct){ + } + countries: (string){ |((string){ "US" }, (string){ "GB" }, (string){ "AU" }) } } } } @@ -206,20 +146,17 @@ } } #Kubernetes: (#struct){ - input: (#struct){ - res1: (#struct){ - route: (#struct){ - } - } - } - output: (#list){ - 0: (#struct){ - route: (#struct){ - } - } - } - Routes: (#struct){ - route: (#struct){ + Routes: (#struct){ + route: (#struct){ + } + } + input: (#struct){ + res1: ~(issue3638.full.#Kubernetes.Routes) + } + output: (#list){ + 0: (#struct){ + route: (#struct){ + } } } } @@ -232,60 +169,8 @@ }, (list){ }) } } - entrypoint: (#list){ - 0: (struct){ - route: (struct){ - default: (struct){ - spec: (#list){ - 0: (#struct){ - refs: (#list){ - 0: (string){ "default" } - } - } - } - } - } - } - } + entrypoint: ~(issue3638.full.used.output) used: (#struct){ - input: (#struct){ - res1: (#struct){ - route: (#struct){ - default: (#struct){ - spec: (#list){ - 0: (#struct){ - refs: (#list){ - 0: (string){ "default" } - } - } - } - } - } - } - } - output: (#list){ - 0: (#struct){ - route: (#struct){ - default: (#struct){ - spec: (list){ |(*(#list){ - 0: (#struct){ - refs: (#list){ - 0: (string){ "default" } - } - other: (#list){ - } - } - }, (#list){ - 0: (#struct){ - refs: (#list){ - 0: (string){ "default" } - } - } - }) } - } - } - } - } Routes: (#struct){ route: (#struct){ default: (#struct){ @@ -299,6 +184,36 @@ } } } + input: (#struct){ + res1: (#struct){ + route: (#struct){ + default: (#struct){ + spec: (#list){ + 0: (#struct){ + refs: (#list){ + 0: (string){ "default" } + } + } + } + } + } + } + } + output: (#list){ + 0: (#struct){ + route: (#struct){ + default: (#struct){ + spec: (#list){ + 0: (#struct){ + refs: (#list){ + 0: (string){ "default" } + } + } + } + } + } + } + } } } reduced: (struct){ @@ -310,12 +225,9 @@ } } out: (struct){ - foo: (#struct){ |(*(#struct){ - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - a: (int){ 1 } - }) } + foo: (#struct){ + a: (int){ 1 } + } } #x: (#struct){ |(*(#struct){ b: (int){ 2 } @@ -332,12 +244,9 @@ } } out: (struct){ - foo: (#struct){ |(*(#struct){ - a: (int){ 1 } - b: (int){ 2 } - }, (#struct){ - a: (int){ 1 } - }) } + foo: (#struct){ + a: (int){ 1 } + } } #x: (#struct){ |(*(#struct){ b: (int){ 2 } -- diff/todo/p3 -- Reordering of error messages. -- diff/explanation -- Overall, the previous errors now passing is acceptable and consistent with the behavior of the new evaluator. issue3638: in V2, there was a spurious default marker to disambiguate a disjunction that should have already been disambiguated. In V3, the disjunction is properly disambiguated. -- out/eval -- Errors: issue3670.a.not_int: field not allowed: ./intpattern.cue:2:6 ./intpattern.cue:3:5 ./intpattern.cue:4:5 t1.c.z: field not allowed: ./in.cue:15:6 ./in.cue:19:5 ./in.cue:19:11 t2.c.z: field not allowed: ./in.cue:23:6 ./in.cue:27:5 ./in.cue:27:11 patternCycle.issue2109.p1.countries: cyclic pattern constraint: ./issue2109.cue:11:15 ./issue2109.cue:10:13 patternCycle.issue2109.p2.countries: cyclic pattern constraint: ./issue2109.cue:15:15 ./issue2109.cue:17:13 patternCycle.issue2109.p3.countries: cyclic pattern constraint: ./issue2109.cue:21:15 ./issue2109.cue:22:13 patternCycle.t1.p1.countries: cyclic pattern constraint: ./issue2109.cue:27:15 ./issue2109.cue:26:13 patternCycle.t1.p2.countries: cyclic pattern constraint: ./issue2109.cue:33:15 ./issue2109.cue:32:13 patternCycle.t1.p3.countries: cyclic pattern constraint: ./issue2109.cue:37:15 ./issue2109.cue:38:13 Result: (_|_){ // [eval] a: (struct){ foo: (struct){ a: (int){ 1 } b: (int){ 1 } name: (string){ "foo" } } } d: (struct){ foo: (struct){ a: (int){ 1 } b: (int){ 1 } name: (string){ "foo" } } foobar: (struct){ c: (int){ 2 } b: (int){ 1 } name: (string){ "foobar" } } } t1: (_|_){ // [eval] #a: (#struct){ } b: (#struct){ f: (int){ 4 } } c: (_|_){ // [eval] z: (_|_){ // [eval] t1.c.z: field not allowed: // ./in.cue:15:6 // ./in.cue:19:5 // ./in.cue:19:11 } } } t2: (_|_){ // [eval] #a: (#struct){ } b: (#struct){ x: (int){ 4 } } c: (_|_){ // [eval] z: (_|_){ // [eval] t2.c.z: field not allowed: // ./in.cue:23:6 // ./in.cue:27:5 // ./in.cue:27:11 } } } issue3670: (_|_){ // [eval] #X: (#struct){ } a: (_|_){ // [eval] not_int: (_|_){ // [eval] issue3670.a.not_int: field not allowed: // ./intpattern.cue:2:6 // ./intpattern.cue:3:5 // ./intpattern.cue:4:5 } } } dual: (_){ _ } patternCycle: (_|_){ // [eval] issue2109: (_|_){ // [eval] p1: (_|_){ // [eval] countries: (_|_){ // [eval] patternCycle.issue2109.p1.countries: cyclic pattern constraint: // ./issue2109.cue:11:15 // ./issue2109.cue:10:13 0: (string){ "US" } 1: (string){ "GB" } 2: (string){ "AU" } } FlagsURLs: (struct){ } } p2: (_|_){ // [eval] FlagsURLs: (struct){ } countries: (_|_){ // [eval] patternCycle.issue2109.p2.countries: cyclic pattern constraint: // ./issue2109.cue:15:15 // ./issue2109.cue:17:13 0: (_|_){// "US" } 1: (_|_){// "GB" } 2: (_|_){// "AU" } } } p3: (_|_){ // [eval] FlagsURLs: (struct){ } countries: (_|_){ // [eval] patternCycle.issue2109.p3.countries: cyclic pattern constraint: // ./issue2109.cue:21:15 // ./issue2109.cue:22:13 0: (_|_){// "US" } 1: (_|_){// "GB" } 2: (_|_){// "AU" } } } } t1: (_|_){ // [eval] p1: (_|_){ // [eval] countries: (_|_){ // [eval] patternCycle.t1.p1.countries: cyclic pattern constraint: // ./issue2109.cue:27:15 // ./issue2109.cue:26:13 } FlagsURLs: (struct){ } } p2: (_|_){ // [eval] countries: (_|_){ // [eval] patternCycle.t1.p2.countries: cyclic pattern constraint: // ./issue2109.cue:33:15 // ./issue2109.cue:32:13 } FlagsURLs: (struct){ } } p3: (_|_){ // [eval] FlagsURLs: (struct){ } countries: (_|_){ // [eval] patternCycle.t1.p3.countries: cyclic pattern constraint: // ./issue2109.cue:37:15 // ./issue2109.cue:38:13 } } } } issue3638: (struct){ full: (struct){ routes: (struct){ default: (struct){ spec: (#list){ 0: (struct){ refs: (#list){ 0: (string){ "default" } } } } } } #Fields: (#struct){ input: (_){ _ } output: (_|_){ // [incomplete] issue3638.full.#Fields.output: cannot range over input (incomplete type _): // ./multi.cue:10:21 } } #Kubernetes: (#struct){ input: (#struct){ res1: (#struct){ route: (#struct){ } } } output: (#list){ 0: (#struct){ route: (#struct){ } } } Routes: (#struct){ route: (#struct){ } } } let HTTPROUTESPEC#1 = (struct){ #x: (#list){ |(*(#list){ 0: (#struct){ other: (#list){ } } }, (list){ }) } } entrypoint: (#list){ 0: (struct){ route: (struct){ default: (struct){ spec: (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } } } } } } used: (#struct){ input: (#struct){ res1: (#struct){ route: (#struct){ default: (#struct){ spec: (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } } } } } } output: (#list){ 0: (#struct){ route: (#struct){ default: (#struct){ spec: (list){ |(*(#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } other: (#list){ } } }, (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } }) } } } } } Routes: (#struct){ route: (#struct){ default: (#struct){ spec: (#list){ 0: (#struct){ refs: (#list){ 0: (string){ "default" } } } } } } } } } reduced: (struct){ input: (struct){ k1: (struct){ foo: (#struct){ a: (int){ 1 } } } } out: (struct){ foo: (#struct){ |(*(#struct){ a: (int){ 1 } b: (int){ 2 } }, (#struct){ a: (int){ 1 } }) } } #x: (#struct){ |(*(#struct){ b: (int){ 2 } }, (#struct){ a: (int){ int } }) } } compare: (struct){ input: (struct){ k1: (struct){ foo: (#struct){ a: (int){ 1 } } } } out: (struct){ foo: (#struct){ |(*(#struct){ a: (int){ 1 } b: (int){ 2 } }, (#struct){ a: (int){ 1 } }) } } #x: (#struct){ |(*(#struct){ b: (int){ 2 } }, (#struct){ a: (int){ int } }) } } } } -- out/compile -- --- in.cue { a: { foo: { a: 1 } [=~"foo"]: { b: 1 name: 〈1;-〉 } } d: (〈0;a〉 & { foobar: { c: 2 } }) t1: { #a: { [(>"e" & <"z")]: int } b: (〈0;#a〉 & { f: 4 }) c: (〈0;#a〉 & { z: 4 }) } t2: { #a: { [("x"|"y")]: int } b: (〈0;#a〉 & { x: 4 }) c: (〈0;#a〉 & { z: 4 }) } } --- intpattern.cue { issue3670: { #X: { [int]: string } a: 〈0;#X〉 a: { not_int: "c" } } dual: { _ [string]: _ [int]: _ } } --- issue2109.cue { patternCycle: { issue2109: { p1: { countries: [ "US", "GB", "AU", ] FlagsURLs: { [or(〈1;countries〉)]: string } 〈0;FlagsURLs〉 } } } patternCycle: { issue2109: { p2: { FlagsURLs: { [or(〈1;countries〉)]: string } 〈0;FlagsURLs〉 countries: [ "US", "GB", "AU", ] } } } patternCycle: { issue2109: { p3: { 〈0;FlagsURLs〉 FlagsURLs: { [or(〈1;countries〉)]: string } countries: [ "US", "GB", "AU", ] } } } patternCycle: { t1: { p1: { countries: ("US"|"GB"|"AU") FlagsURLs: { [〈1;countries〉]: string } 〈0;FlagsURLs〉 } } } patternCycle: { t1: { p2: { 〈0;FlagsURLs〉 countries: ("US"|"GB"|"AU") FlagsURLs: { [〈1;countries〉]: string } } } } patternCycle: { t1: { p3: { 〈0;FlagsURLs〉 FlagsURLs: { [〈1;countries〉]: string } countries: ("US"|"GB"|"AU") } } } } --- multi.cue { issue3638: { full: { routes: { default: {} } routes: { [string]: { spec: [ { refs: [ { "default" }, ] }, ] } } #Fields: { input: _ output: [ for _, x in 〈1;input〉 { 〈1;x〉 }, ] ... } #Kubernetes: { (〈1;#Fields〉 & { Routes: { route: { [_]: { spec!: 〈5;let HTTPROUTESPEC#1〉.#x } } } }) 〈1;#Fields〉 Routes: _ input: { res1: 〈1;Routes〉 } } let HTTPROUTESPEC#1 = { #x: ([ ...{ refs: [ ...{ string }, ] }, ]|*[ { other: [] }, ]) } entrypoint: 〈0;used〉.output used: (〈0;#Kubernetes〉 & { Routes: { route: 〈2;routes〉 } }) } } issue3638: { reduced: { input: { k1: { [string]: { a: 1 } } } input: { k1: { foo: 〈2;#x〉 } } out: { for _, x in 〈1;input〉 { 〈1;x〉 } for _, x in 〈1;input〉 { 〈1;x〉 } } #x: ({ a: int }|*{ b: 2 }) } } issue3638: { compare: { input: { k1: { foo: { a: 1 } } } input: { k1: { foo: 〈2;#x〉 } } out: { for _, x in 〈1;input〉 { 〈1;x〉 } for _, x in 〈1;input〉 { 〈1;x〉 } } #x: ({ a: int }|*{ b: 2 }) } } } cue-lang-cue-db9cc73/cue/testdata/eval/closed_disjunction.txtar000066400000000000000000000075721474664451600247750ustar00rootroot00000000000000-- in.cue -- #A: { b?: int *{} | {c?: int} | {d?: int} | {e?: int} } a: #A & { b: 3 c: 3 } b: #A & { c: 3 d: 4 } -- out/eval/stats -- Leaks: 0 Freed: 46 Reused: 39 Allocs: 7 Retain: 0 Unifications: 34 Conjuncts: 60 Disjuncts: 46 -- out/evalalpha -- Errors: b: 2 errors in empty disjunction: b.c: field not allowed: ./in.cue:12:2 b.d: field not allowed: ./in.cue:13:2 Result: (_|_){ // [eval] #A: (#struct){ |(*(#struct){ b?: (int){ int } }, (#struct){ b?: (int){ int } c?: (int){ int } }, (#struct){ b?: (int){ int } d?: (int){ int } }, (#struct){ b?: (int){ int } e?: (int){ int } }) } a: (#struct){ b: (int){ 3 } c: (int){ 3 } } b: (_|_){ // [eval] b: 2 errors in empty disjunction: // b.c: field not allowed: // ./in.cue:12:2 // b.d: field not allowed: // ./in.cue:13:2 c: (int){ 3 } d: (int){ 4 } b?: (int){ int } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,16 +1,8 @@ Errors: b: 2 errors in empty disjunction: b.c: field not allowed: - ./in.cue:1:5 - ./in.cue:3:2 - ./in.cue:3:3 - ./in.cue:11:4 ./in.cue:12:2 b.d: field not allowed: - ./in.cue:1:5 - ./in.cue:3:2 - ./in.cue:3:8 - ./in.cue:11:4 ./in.cue:13:2 Result: @@ -35,34 +27,11 @@ b: (_|_){ // [eval] b: 2 errors in empty disjunction: // b.c: field not allowed: - // ./in.cue:1:5 - // ./in.cue:3:2 - // ./in.cue:3:3 - // ./in.cue:11:4 // ./in.cue:12:2 // b.d: field not allowed: - // ./in.cue:1:5 - // ./in.cue:3:2 - // ./in.cue:3:8 - // ./in.cue:11:4 // ./in.cue:13:2 + c: (int){ 3 } + d: (int){ 4 } b?: (int){ int } - c: (_|_){ - // [eval] b.c: field not allowed: - // ./in.cue:1:5 - // ./in.cue:3:2 - // ./in.cue:3:32 - // ./in.cue:11:4 - // ./in.cue:12:2 - } - d: (_|_){ - // [eval] b.d: field not allowed: - // ./in.cue:1:5 - // ./in.cue:3:2 - // ./in.cue:3:32 - // ./in.cue:11:4 - // ./in.cue:13:2 - } - e?: (int){ int } } } -- diff/todo/p3 -- Missing error positions. -- diff/explanation -- Dropping e? is correct. -- out/eval -- Errors: b: 2 errors in empty disjunction: b.c: field not allowed: ./in.cue:1:5 ./in.cue:3:2 ./in.cue:3:3 ./in.cue:11:4 ./in.cue:12:2 b.d: field not allowed: ./in.cue:1:5 ./in.cue:3:2 ./in.cue:3:8 ./in.cue:11:4 ./in.cue:13:2 Result: (_|_){ // [eval] #A: (#struct){ |(*(#struct){ b?: (int){ int } }, (#struct){ b?: (int){ int } c?: (int){ int } }, (#struct){ b?: (int){ int } d?: (int){ int } }, (#struct){ b?: (int){ int } e?: (int){ int } }) } a: (#struct){ b: (int){ 3 } c: (int){ 3 } } b: (_|_){ // [eval] b: 2 errors in empty disjunction: // b.c: field not allowed: // ./in.cue:1:5 // ./in.cue:3:2 // ./in.cue:3:3 // ./in.cue:11:4 // ./in.cue:12:2 // b.d: field not allowed: // ./in.cue:1:5 // ./in.cue:3:2 // ./in.cue:3:8 // ./in.cue:11:4 // ./in.cue:13:2 b?: (int){ int } c: (_|_){ // [eval] b.c: field not allowed: // ./in.cue:1:5 // ./in.cue:3:2 // ./in.cue:3:32 // ./in.cue:11:4 // ./in.cue:12:2 } d: (_|_){ // [eval] b.d: field not allowed: // ./in.cue:1:5 // ./in.cue:3:2 // ./in.cue:3:32 // ./in.cue:11:4 // ./in.cue:13:2 } e?: (int){ int } } } -- out/compile -- --- in.cue { #A: { b?: int (*{}|{ c?: int }|{ d?: int }|{ e?: int }) } a: (〈0;#A〉 & { b: 3 c: 3 }) b: (〈0;#A〉 & { c: 3 d: 4 }) } cue-lang-cue-db9cc73/cue/testdata/eval/closedness.txtar000066400000000000000000004665371474664451600232670ustar00rootroot00000000000000// Issue #852 -- in.cue -- #E: { c: int } #A: { b: int q: { #E d: int } } a: #A & { b: 3 q: { c: 2 e: 43 } } // `a` is evaluated through the comprehension first. Ensure that // this does not bypass closedness checks. issue852: { #A: { [=~"^a-z$"]: string } a: #A a: Foo: "foo" for k, v in a { b: "\(k)": v } } dynamic: { #D: { key: "foo" (key): int } d: #D & {foo: 3} } -- embed.cue -- issue3325: ok: { #Items: [Name=string]: { name: Name } #Base: { name: "base" type: string items: #Items } #Extended: #Base & { type: "extended" items: "my-item": {} } broken: { #Base #Extended } works: { #Extended #Base } } patterns: shallow: { #a: [>="k"]: int #b: [<="m"]: int #c: [>="w"]: int #d: [<="y"]: int single: { X: #a // "k" <= x err: X err: j: 3 ok: X ok: k: 3 } and: p1: { X: #a & #b // "k" <= x && x <= "m" err: X err: j: 3 ok: X ok: k: 3 } and: p2: { X: #b & #a // "k" <= x && x <= "m" err: X err: j: 3 ok: X ok: k: 3 } andEmbed: p1: { X: { #a & #b } // "k" <= x && x <= "m" err: X err: j: 3 ok: X ok: k: 3 } andEmbed: p2: { X: { #b & #a } // "k" <= x && x <= "m" err: X err: j: 3 ok: X ok: k: 3 } orEmbed: p1: { X: { #a, #b } // "k" <= x && x <= "m" ok1: X ok1: j: 3 ok2: X ok2: k: 3 } orEmbed: p2: { X: { #b, #a } // "k" <= x && x <= "m" ok1: X ok1: j: 3 ok2: X ok2: k: 3 } andOrEmbed: t1: p1: { // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") X: { #a & #b #c & #d } err1: X err1: j: 3 ok1: X ok1: k: 3 } andOrEmbed: t1: p2: { // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") X: { #c & #d #a & #b } err1: X err1: j: 3 ok1: X ok1: k: 3 } andOrEmbed: t2:{ // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") || x == "p" X: { #a & #b #c & #d ["p"]: int } err1: X err1: j: 3 ok1: X ok1: k: 3 ok2: X ok2: p: 3 } // The last indirection is not a definition. indirect: { a: [>="k"]: int #a: a p1: { // XXX // link to code X: #a err1: X err1: j: 3 err2: X & __no_sharing err2: j: 3 ok: X ok:k: 3 } p2: { #a: a & __no_sharing X: #a err1: X err1: j: 3 err2: X & __no_sharing err2: j: 3 ok: X ok: k: 3 } p3: { X: #a & __no_sharing err1: X err1: j: 3 err2: X & __no_sharing err2: j: 3 ok: X ok: k: 3 } p4: { #a: a & __no_sharing X: #a X: #a & __no_sharing err1: X err1: j: 3 err2: X & __no_sharing err2: j: 3 ok: X ok: k: 3 } } } patterns: nested: { #a: x: y: [>="k"]: int #b: x: y: [<="m"]: int #c: x: y: [>="w"]: int #d: x: y: [<="y"]: int single: { X: #a // "k" <= x err: X err: x: y: j: 3 ok: X ok: x: y: k: 3 } and: p1: { X: #a & #b // "k" <= x && x <= "m" err: X err: x: y: j: 3 ok: X ok: x: y: k: 3 } and: p2: { X: #b & #a // "k" <= x && x <= "m" err: X err: x: y: j: 3 ok: X ok: x: y: k: 3 } andEmbed: p1: { X: { #a & #b } // "k" <= x && x <= "m" err: X err: x: y: j: 3 ok: X ok: x: y: k: 3 } andEmbed: p2: { X: { #b & #a } // "k" <= x && x <= "m" err: X err: x: y: j: 3 ok: X ok: x: y: k: 3 } orEmbed: p1: { X: { #a, #b } // "k" <= x && x <= "m" ok1: X ok1: x: y: j: 3 ok2: X ok2: x: y: k: 3 } orEmbed: p2: { X: { #b, #a } // "k" <= x && x <= "m" ok1: X ok1: x: y: j: 3 ok2: X ok2: x: y: k: 3 } andOrEmbed: t1: p1: { // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") X: { #a & #b #c & #d } err1: X err1: x: y: j: 3 ok1: X ok1: x: y: k: 3 } andOrEmbed: t1: p2: { // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") X: { #c & #d #a & #b } err1: X err1: x: y: j: 3 ok1: X ok1: x: y: k: 3 } andOrEmbed: t2:{ // ("k" <= x && x <= "m") || ("w" <= x && x <= "y") || x == "p" X: { #a & #b #c & #d ["p"]: int } err1: X err1: x: y: j: 3 ok1: X ok1: x: y: k: 3 ok2: X ok2: x: y: p: 3 } // The last indirection is not a definition. indirect: { a: x: y: [>="k"]: int #a: a p1: { X: #a err1: X err1: x: y: j: 3 err2: X & __no_sharing err2: x: y: j: 3 ok: X ok: x: y: k: 3 } p2: { #a: a & __no_sharing X: #a err1: X err1: x: y: j: 3 err2: X & __no_sharing err2: x: y: j: 3 ok: X ok: x: y: k: 3 } p3: { X: #a & __no_sharing err1: X err1: x: y: j: 3 err2: X & __no_sharing err2: x: y: j: 3 ok: X ok: x: y: k: 3 } p4: { #a: a & __no_sharing X: #a X: #a & __no_sharing err1: X err1: x: y: j: 3 err2: X & __no_sharing err2: x: y: j: 3 ok: X ok: x: y: k: 3 } } } -- reroot.cue -- import "list" issue3330: { let: ok: { #struct: { let empty = {} field: null | { n: int } field: empty & { n: 3 } } out: list.Concat([[#struct]]) } matthew: ok1: { #struct: { field: { n: 3 } & g g: {} } out: #struct & {} } matthew: ok2: { #struct: { field: { n: 3 } & g g: {} } out: #struct out2: out & {} } } issue3331: { original: ok: { #A: { let b = {} c: b & { d: 1 } } list.Concat([[#A]]) } variant1: ok: { #A: { let b = {} c: b & { d: 1 } } [[#A]] } } // indirect tests cases where a reference indirectly crosses a node that // references a definition, thereby indirectly referencing it. indirect: { embed: err1: { #A: { x: {#x, #y} zx: x.a } #x: {a: b: 1} #y: {a: c: 2} b: #A b1: b.zx b1: d: 1 // This should fail as b.zx crosses a reference to definition. } closed: err1: { X: { // refer to a value that will be closed after unification in another struct. a: b b: {} a: e: 1 } Y: X Y: { b: c c: #X } #X: {} } } // nested.a nested: ok1: { #A: { b: {} #B: { c: b & { d: 1 } } } x: #A } nested: embed: ok: { x: #A #A: { k } k: { d: b & {e: int} b: {} } } // nested.b tests insertion of a field (b) that has a conjunct rooted within // the tree it is referred in as well as a conjunct outside of it that refers // to a definition. nested: err1: { x: #A #A: { b: f: 1 v: #V #V: { c: b & { // Fails as #B is not compatible. d: 1 } } } x: b: #B #B: g: 1 } nested: err2: { #A: { b: {} // error only reported here. c: b & { // error (g not allowed) not reported here, as it would be okay if b // were valid. Instead, it is reported at b only. This is conform // the spec. d: 1 } } x: #A x: b: g: 1 } inline: { #x: y: z?: name: string err1: (#x & {y: z: _}).y.z & { name: "a" age1: 5 // not allowed } err2: (#x.y & {z: _}).z & { name: "a" age2: 5 // not allowed } } // minInDef defines examples where a definition is mixed into an open struct, // where then this struct refers to a field that is closed by the definition. mixInDef: { refInside: { #x: b: c: {d: {}, e: f: {} } a: #x a: b: c: d: {} a: b: c: e: c.d } refEdge: { #x: c: {d: {}, e: f: {} } a: #x a: c: d: {} a: c: e: c.d } refOutside: { #x: c: {d: {}, e: f: {} } a: #x a: c: d: {} a: c: e: a.c.d // crosses definition } } issue3601: original: { out: { #Transform.output } #Transform: output: (#Patch & {}).output #Patch: { target: {} output: foo: { final: target final: version: "v1" } } } issue3601: originalNoShare: { // Like the original, but with explicit no sharing. out: { #Transform.output } #Transform: output: (#Patch & __no_sharing).output #Patch: { target: {} output: foo: { final: target final: version: "v1" } } } issue3601: reduced: { #X: { a: b: c: "v1" a: b: empty empty: {} } original: { Y: (#X & __no_sharing).a out: Y & __no_sharing } moreInlining: { out: (#X & {}).a & {} } noInline: { Y: #X & __no_sharing Z: Y & __no_sharing out: Z.a & __no_sharing } moreNesting: { #X: { a: b: c: d: "v1" a: b: c: empty empty: {} } Y: (#X.a & __no_sharing).b Z: Y & __no_sharing } } -- validation.cue -- import "list" issue3332: { #def: field: list.MinItems(1) use: #def & { field: ["value"] } } -- out/eval/stats -- Leaks: 12 Freed: 748 Reused: 740 Allocs: 20 Retain: 77 Unifications: 754 Conjuncts: 1923 Disjuncts: 826 -- out/eval -- Errors: a.q.e: field not allowed: ./in.cue:1:5 ./in.cue:6:5 ./in.cue:7:3 ./in.cue:11:4 ./in.cue:15:3 indirect.closed.err1.Y.a.e: field not allowed: ./reroot.cue:73:7 ./reroot.cue:74:7 ./reroot.cue:75:7 ./reroot.cue:77:6 ./reroot.cue:79:7 ./reroot.cue:80:7 ./reroot.cue:82:7 issue852.a.Foo: field not allowed: ./in.cue:22:6 ./in.cue:26:5 ./in.cue:28:5 nested.err1.x.#V.c.d: field not allowed: ./reroot.cue:112:5 ./reroot.cue:114:6 ./reroot.cue:117:7 ./reroot.cue:118:5 ./reroot.cue:122:8 ./reroot.cue:123:6 nested.err1.x.#V.c.f: field not allowed: ./reroot.cue:112:5 ./reroot.cue:114:6 ./reroot.cue:117:7 ./reroot.cue:117:11 ./reroot.cue:122:8 ./reroot.cue:123:6 nested.err1.x.b.f: field not allowed: ./reroot.cue:112:5 ./reroot.cue:114:6 ./reroot.cue:122:8 ./reroot.cue:123:6 nested.err1.x.b.g: field not allowed: ./reroot.cue:112:5 ./reroot.cue:114:6 ./reroot.cue:122:8 ./reroot.cue:123:6 nested.err1.x.v.c.d: field not allowed: ./reroot.cue:112:5 ./reroot.cue:114:6 ./reroot.cue:115:6 ./reroot.cue:117:7 ./reroot.cue:118:5 ./reroot.cue:122:8 ./reroot.cue:123:6 nested.err1.x.v.c.f: field not allowed: ./reroot.cue:112:5 ./reroot.cue:114:6 ./reroot.cue:115:6 ./reroot.cue:117:7 ./reroot.cue:117:11 ./reroot.cue:122:8 ./reroot.cue:123:6 nested.err2.x.b.g: field not allowed: ./reroot.cue:128:6 ./reroot.cue:136:5 ./reroot.cue:137:8 patterns.nested.and.p1.err.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:221:6 ./embed.cue:221:11 ./embed.cue:223:8 ./embed.cue:224:14 patterns.nested.and.p2.err.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:231:6 ./embed.cue:231:11 ./embed.cue:232:8 ./embed.cue:233:14 patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:240:8 ./embed.cue:240:13 ./embed.cue:242:8 ./embed.cue:243:14 patterns.nested.andEmbed.p2.err.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:250:8 ./embed.cue:250:13 ./embed.cue:251:8 ./embed.cue:252:14 patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:208:12 ./embed.cue:209:12 ./embed.cue:280:4 ./embed.cue:280:9 ./embed.cue:281:4 ./embed.cue:281:9 ./embed.cue:283:9 ./embed.cue:284:15 patterns.nested.andOrEmbed.t1.p2.err1.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:208:12 ./embed.cue:209:12 ./embed.cue:293:4 ./embed.cue:293:9 ./embed.cue:294:4 ./embed.cue:294:9 ./embed.cue:296:9 ./embed.cue:297:15 patterns.nested.andOrEmbed.t2.err1.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:208:12 ./embed.cue:209:12 ./embed.cue:306:4 ./embed.cue:306:9 ./embed.cue:307:4 ./embed.cue:307:9 ./embed.cue:310:9 ./embed.cue:311:15 patterns.nested.andOrEmbed.t2.ok2.x.y.p: field not allowed: ./embed.cue:206:12 ./embed.cue:207:12 ./embed.cue:208:12 ./embed.cue:209:12 ./embed.cue:306:4 ./embed.cue:306:9 ./embed.cue:307:4 ./embed.cue:307:9 ./embed.cue:316:8 ./embed.cue:317:14 patterns.nested.indirect.p1.err1.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:323:7 ./embed.cue:326:7 ./embed.cue:327:10 ./embed.cue:328:16 patterns.nested.indirect.p1.err2.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:323:7 ./embed.cue:326:7 ./embed.cue:330:10 ./embed.cue:331:16 patterns.nested.indirect.p2.err1.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:338:8 ./embed.cue:339:7 ./embed.cue:341:10 ./embed.cue:342:16 patterns.nested.indirect.p2.err2.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:338:8 ./embed.cue:339:7 ./embed.cue:344:10 ./embed.cue:345:16 patterns.nested.indirect.p3.err1.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:323:7 ./embed.cue:352:7 ./embed.cue:354:10 ./embed.cue:355:16 patterns.nested.indirect.p3.err2.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:323:7 ./embed.cue:352:7 ./embed.cue:357:10 ./embed.cue:358:16 patterns.nested.indirect.p4.err1.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:365:8 ./embed.cue:366:7 ./embed.cue:369:10 ./embed.cue:370:16 patterns.nested.indirect.p4.err2.x.y.j: field not allowed: ./embed.cue:322:12 ./embed.cue:365:8 ./embed.cue:366:7 ./embed.cue:372:10 ./embed.cue:373:16 patterns.nested.single.err.x.y.j: field not allowed: ./embed.cue:206:12 ./embed.cue:212:6 ./embed.cue:213:8 ./embed.cue:214:14 patterns.shallow.and.p1.err.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:45:6 ./embed.cue:45:11 ./embed.cue:47:8 ./embed.cue:48:8 patterns.shallow.and.p2.err.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:55:6 ./embed.cue:55:11 ./embed.cue:56:8 ./embed.cue:57:8 patterns.shallow.andEmbed.p1.err.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:64:6 ./embed.cue:64:8 ./embed.cue:64:13 ./embed.cue:66:8 ./embed.cue:67:8 patterns.shallow.andEmbed.p2.err.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:74:6 ./embed.cue:74:8 ./embed.cue:74:13 ./embed.cue:75:8 ./embed.cue:76:8 patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:32:6 ./embed.cue:33:6 ./embed.cue:103:6 ./embed.cue:104:4 ./embed.cue:104:9 ./embed.cue:105:4 ./embed.cue:105:9 ./embed.cue:107:9 ./embed.cue:108:9 patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:32:6 ./embed.cue:33:6 ./embed.cue:116:6 ./embed.cue:117:4 ./embed.cue:117:9 ./embed.cue:118:4 ./embed.cue:118:9 ./embed.cue:120:9 ./embed.cue:121:9 patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: ./embed.cue:30:6 ./embed.cue:31:6 ./embed.cue:32:6 ./embed.cue:33:6 ./embed.cue:129:6 ./embed.cue:130:4 ./embed.cue:130:9 ./embed.cue:131:4 ./embed.cue:131:9 ./embed.cue:134:9 ./embed.cue:135:9 patterns.shallow.indirect.p1.err1.j: field not allowed: ./embed.cue:146:6 ./embed.cue:147:7 ./embed.cue:150:7 ./embed.cue:151:10 ./embed.cue:152:10 patterns.shallow.indirect.p1.err2.j: field not allowed: ./embed.cue:146:6 ./embed.cue:147:7 ./embed.cue:150:7 ./embed.cue:154:10 ./embed.cue:155:10 patterns.shallow.indirect.p2.err1.j: field not allowed: ./embed.cue:146:6 ./embed.cue:162:8 ./embed.cue:163:7 ./embed.cue:165:10 ./embed.cue:166:10 patterns.shallow.indirect.p2.err2.j: field not allowed: ./embed.cue:146:6 ./embed.cue:162:8 ./embed.cue:163:7 ./embed.cue:168:10 ./embed.cue:169:10 patterns.shallow.indirect.p3.err1.j: field not allowed: ./embed.cue:146:6 ./embed.cue:147:7 ./embed.cue:176:7 ./embed.cue:178:10 ./embed.cue:179:10 patterns.shallow.indirect.p3.err2.j: field not allowed: ./embed.cue:146:6 ./embed.cue:147:7 ./embed.cue:176:7 ./embed.cue:181:10 ./embed.cue:182:10 patterns.shallow.indirect.p4.err1.j: field not allowed: ./embed.cue:146:6 ./embed.cue:189:8 ./embed.cue:190:7 ./embed.cue:193:10 ./embed.cue:194:10 patterns.shallow.indirect.p4.err2.j: field not allowed: ./embed.cue:146:6 ./embed.cue:189:8 ./embed.cue:190:7 ./embed.cue:196:10 ./embed.cue:197:10 patterns.shallow.single.err.j: field not allowed: ./embed.cue:30:6 ./embed.cue:36:6 ./embed.cue:37:8 ./embed.cue:38:8 Result: (_|_){ // [eval] issue3325: (struct){ ok: (struct){ #Items: (#struct){ } #Base: (#struct){ name: (string){ "base" } type: (string){ string } items: (#struct){ } } #Extended: (#struct){ name: (string){ "base" } type: (string){ "extended" } items: (#struct){ "my-item": (#struct){ name: (string){ "my-item" } } } } broken: (#struct){ name: (string){ "base" } type: (string){ "extended" } items: (#struct){ "my-item": (#struct){ name: (string){ "my-item" } } } } works: (#struct){ name: (string){ "base" } type: (string){ "extended" } items: (#struct){ "my-item": (#struct){ name: (string){ "my-item" } } } } } } patterns: (_|_){ // [eval] shallow: (_|_){ // [eval] #a: (#struct){ } #b: (#struct){ } #c: (#struct){ } #d: (#struct){ } single: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.single.err.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:36:6 // ./embed.cue:37:8 // ./embed.cue:38:8 } } ok: (#struct){ k: (int){ 3 } } } and: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.and.p1.err.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:45:6 // ./embed.cue:45:11 // ./embed.cue:47:8 // ./embed.cue:48:8 } } ok: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.and.p2.err.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:55:6 // ./embed.cue:55:11 // ./embed.cue:56:8 // ./embed.cue:57:8 } } ok: (#struct){ k: (int){ 3 } } } } andEmbed: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andEmbed.p1.err.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:64:6 // ./embed.cue:64:8 // ./embed.cue:64:13 // ./embed.cue:66:8 // ./embed.cue:67:8 } } ok: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andEmbed.p2.err.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:74:6 // ./embed.cue:74:8 // ./embed.cue:74:13 // ./embed.cue:75:8 // ./embed.cue:76:8 } } ok: (#struct){ k: (int){ 3 } } } } orEmbed: (struct){ p1: (struct){ X: (#struct){ } ok1: (#struct){ j: (int){ 3 } } ok2: (#struct){ k: (int){ 3 } } } p2: (struct){ X: (#struct){ } ok1: (#struct){ j: (int){ 3 } } ok2: (#struct){ k: (int){ 3 } } } } andOrEmbed: (_|_){ // [eval] t1: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:32:6 // ./embed.cue:33:6 // ./embed.cue:103:6 // ./embed.cue:104:4 // ./embed.cue:104:9 // ./embed.cue:105:4 // ./embed.cue:105:9 // ./embed.cue:107:9 // ./embed.cue:108:9 } } ok1: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:32:6 // ./embed.cue:33:6 // ./embed.cue:116:6 // ./embed.cue:117:4 // ./embed.cue:117:9 // ./embed.cue:118:4 // ./embed.cue:118:9 // ./embed.cue:120:9 // ./embed.cue:121:9 } } ok1: (#struct){ k: (int){ 3 } } } } t2: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: // ./embed.cue:30:6 // ./embed.cue:31:6 // ./embed.cue:32:6 // ./embed.cue:33:6 // ./embed.cue:129:6 // ./embed.cue:130:4 // ./embed.cue:130:9 // ./embed.cue:131:4 // ./embed.cue:131:9 // ./embed.cue:134:9 // ./embed.cue:135:9 } } ok1: (#struct){ k: (int){ 3 } } ok2: (#struct){ p: (int){ 3 } } } } indirect: (_|_){ // [eval] a: (struct){ } #a: (#struct){ } p1: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p1.err1.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:147:7 // ./embed.cue:150:7 // ./embed.cue:151:10 // ./embed.cue:152:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p1.err2.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:147:7 // ./embed.cue:150:7 // ./embed.cue:154:10 // ./embed.cue:155:10 } } ok: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] #a: (#struct){ } X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p2.err1.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:162:8 // ./embed.cue:163:7 // ./embed.cue:165:10 // ./embed.cue:166:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p2.err2.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:162:8 // ./embed.cue:163:7 // ./embed.cue:168:10 // ./embed.cue:169:10 } } ok: (#struct){ k: (int){ 3 } } } p3: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p3.err1.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:147:7 // ./embed.cue:176:7 // ./embed.cue:178:10 // ./embed.cue:179:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p3.err2.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:147:7 // ./embed.cue:176:7 // ./embed.cue:181:10 // ./embed.cue:182:10 } } ok: (#struct){ k: (int){ 3 } } } p4: (_|_){ // [eval] #a: (#struct){ } X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p4.err1.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:189:8 // ./embed.cue:190:7 // ./embed.cue:193:10 // ./embed.cue:194:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p4.err2.j: field not allowed: // ./embed.cue:146:6 // ./embed.cue:189:8 // ./embed.cue:190:7 // ./embed.cue:196:10 // ./embed.cue:197:10 } } ok: (#struct){ k: (int){ 3 } } } } } nested: (_|_){ // [eval] #a: (#struct){ x: (#struct){ y: (#struct){ } } } #b: (#struct){ x: (#struct){ y: (#struct){ } } } #c: (#struct){ x: (#struct){ y: (#struct){ } } } #d: (#struct){ x: (#struct){ y: (#struct){ } } } single: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.single.err.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:212:6 // ./embed.cue:213:8 // ./embed.cue:214:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } and: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.and.p1.err.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:221:6 // ./embed.cue:221:11 // ./embed.cue:223:8 // ./embed.cue:224:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.and.p2.err.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:231:6 // ./embed.cue:231:11 // ./embed.cue:232:8 // ./embed.cue:233:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } andEmbed: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:240:8 // ./embed.cue:240:13 // ./embed.cue:242:8 // ./embed.cue:243:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andEmbed.p2.err.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:250:8 // ./embed.cue:250:13 // ./embed.cue:251:8 // ./embed.cue:252:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } orEmbed: (struct){ p1: (struct){ X: (#struct){ x: (#struct){ y: (#struct){ } } } ok1: (#struct){ x: (#struct){ y: (#struct){ j: (int){ 3 } } } } ok2: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (struct){ X: (#struct){ x: (#struct){ y: (#struct){ } } } ok1: (#struct){ x: (#struct){ y: (#struct){ j: (int){ 3 } } } } ok2: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } andOrEmbed: (_|_){ // [eval] t1: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:208:12 // ./embed.cue:209:12 // ./embed.cue:280:4 // ./embed.cue:280:9 // ./embed.cue:281:4 // ./embed.cue:281:9 // ./embed.cue:283:9 // ./embed.cue:284:15 } } } } ok1: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t1.p2.err1.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:208:12 // ./embed.cue:209:12 // ./embed.cue:293:4 // ./embed.cue:293:9 // ./embed.cue:294:4 // ./embed.cue:294:9 // ./embed.cue:296:9 // ./embed.cue:297:15 } } } } ok1: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } t2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t2.err1.x.y.j: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:208:12 // ./embed.cue:209:12 // ./embed.cue:306:4 // ./embed.cue:306:9 // ./embed.cue:307:4 // ./embed.cue:307:9 // ./embed.cue:310:9 // ./embed.cue:311:15 } } } } ok1: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } ok2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] p: (_|_){ // [eval] patterns.nested.andOrEmbed.t2.ok2.x.y.p: field not allowed: // ./embed.cue:206:12 // ./embed.cue:207:12 // ./embed.cue:208:12 // ./embed.cue:209:12 // ./embed.cue:306:4 // ./embed.cue:306:9 // ./embed.cue:307:4 // ./embed.cue:307:9 // ./embed.cue:316:8 // ./embed.cue:317:14 } } } } } } indirect: (_|_){ // [eval] a: (struct){ x: (struct){ y: (struct){ } } } #a: (#struct){ x: (#struct){ y: (#struct){ } } } p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p1.err1.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:323:7 // ./embed.cue:326:7 // ./embed.cue:327:10 // ./embed.cue:328:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p1.err2.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:323:7 // ./embed.cue:326:7 // ./embed.cue:330:10 // ./embed.cue:331:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] #a: (#struct){ x: (#struct){ y: (#struct){ } } } X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p2.err1.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:338:8 // ./embed.cue:339:7 // ./embed.cue:341:10 // ./embed.cue:342:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p2.err2.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:338:8 // ./embed.cue:339:7 // ./embed.cue:344:10 // ./embed.cue:345:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p3: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p3.err1.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:323:7 // ./embed.cue:352:7 // ./embed.cue:354:10 // ./embed.cue:355:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p3.err2.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:323:7 // ./embed.cue:352:7 // ./embed.cue:357:10 // ./embed.cue:358:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p4: (_|_){ // [eval] #a: (#struct){ x: (#struct){ y: (#struct){ } } } X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p4.err1.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:365:8 // ./embed.cue:366:7 // ./embed.cue:369:10 // ./embed.cue:370:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p4.err2.x.y.j: field not allowed: // ./embed.cue:322:12 // ./embed.cue:365:8 // ./embed.cue:366:7 // ./embed.cue:372:10 // ./embed.cue:373:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } } } #E: (#struct){ c: (int){ int } } #A: (#struct){ b: (int){ int } q: (#struct){ c: (int){ int } d: (int){ int } } } a: (_|_){ // [eval] b: (int){ 3 } q: (_|_){ // [eval] c: (int){ 2 } d: (int){ int } e: (_|_){ // [eval] a.q.e: field not allowed: // ./in.cue:1:5 // ./in.cue:6:5 // ./in.cue:7:3 // ./in.cue:11:4 // ./in.cue:15:3 } } } issue852: (_|_){ // [eval] issue852.a.Foo: field not allowed: // ./in.cue:22:6 // ./in.cue:26:5 // ./in.cue:28:5 #A: (#struct){ } a: (_|_){ // [eval] Foo: (_|_){ // [eval] issue852.a.Foo: field not allowed: // ./in.cue:22:6 // ./in.cue:26:5 // ./in.cue:28:5 } } } dynamic: (struct){ #D: (#struct){ key: (string){ "foo" } foo: (int){ int } } d: (#struct){ key: (string){ "foo" } foo: (int){ 3 } } } issue3330: (struct){ let: (struct){ ok: (struct){ #struct: (#struct){ let empty#1 = (#struct){ } field: (#struct){ n: (int){ 3 } } } out: (#list){ 0: (#struct){ let empty#1 = (#struct){ } field: (#struct){ n: (int){ 3 } } } } } } matthew: (struct){ ok1: (struct){ #struct: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } } ok2: (struct){ #struct: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out2: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } } } } issue3331: (struct){ original: (struct){ ok: (#list){ #A: (#struct){ let b#2 = (#struct){ } c: (#struct){ d: (int){ 1 } } } 0: (#struct){ let b#2 = (#struct){ } c: (#struct){ d: (int){ 1 } } } } } variant1: (struct){ ok: (#list){ #A: (#struct){ let b#3 = (#struct){ } c: (#struct){ d: (int){ 1 } } } 0: (#list){ 0: (#struct){ let b#3 = (#struct){ } c: (#struct){ d: (int){ 1 } } } } } } } indirect: (_|_){ // [eval] embed: (struct){ err1: (struct){ #A: (#struct){ x: (#struct){ a: (#struct){ b: (int){ 1 } c: (int){ 2 } } } zx: (#struct){ b: (int){ 1 } c: (int){ 2 } } } #x: (#struct){ a: (#struct){ b: (int){ 1 } } } #y: (#struct){ a: (#struct){ c: (int){ 2 } } } b: (#struct){ x: (#struct){ a: (#struct){ b: (int){ 1 } c: (int){ 2 } } } zx: (#struct){ b: (int){ 1 } c: (int){ 2 } } } b1: (struct){ b: (int){ 1 } c: (int){ 2 } d: (int){ 1 } } } } closed: (_|_){ // [eval] err1: (_|_){ // [eval] X: (struct){ a: (struct){ e: (int){ 1 } } b: (struct){ } } Y: (_|_){ // [eval] a: (_|_){ // [eval] e: (_|_){ // [eval] indirect.closed.err1.Y.a.e: field not allowed: // ./reroot.cue:73:7 // ./reroot.cue:74:7 // ./reroot.cue:75:7 // ./reroot.cue:77:6 // ./reroot.cue:79:7 // ./reroot.cue:80:7 // ./reroot.cue:82:7 } } b: (#struct){ } c: (#struct){ } } #X: (#struct){ } } } } nested: (_|_){ // [eval] ok1: (struct){ #A: (#struct){ b: (#struct){ } #B: (#struct){ c: (#struct){ d: (int){ 1 } } } } x: (#struct){ b: (#struct){ } #B: (#struct){ c: (#struct){ d: (int){ 1 } } } } } embed: (struct){ ok: (struct){ x: (#struct){ d: (#struct){ e: (int){ int } } b: (#struct){ } } #A: (#struct){ d: (#struct){ e: (int){ int } } b: (#struct){ } } k: (struct){ d: (struct){ e: (int){ int } } b: (struct){ } } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] b: (_|_){ // [eval] f: (_|_){ // [eval] nested.err1.x.b.f: field not allowed: // ./reroot.cue:112:5 // ./reroot.cue:114:6 // ./reroot.cue:122:8 // ./reroot.cue:123:6 } g: (_|_){ // [eval] nested.err1.x.b.g: field not allowed: // ./reroot.cue:112:5 // ./reroot.cue:114:6 // ./reroot.cue:122:8 // ./reroot.cue:123:6 } } v: (_|_){ // [eval] c: (_|_){ // [eval] f: (_|_){ // [eval] nested.err1.x.v.c.f: field not allowed: // ./reroot.cue:112:5 // ./reroot.cue:114:6 // ./reroot.cue:115:6 // ./reroot.cue:117:7 // ./reroot.cue:117:11 // ./reroot.cue:122:8 // ./reroot.cue:123:6 } g: (int){ 1 } d: (_|_){ // [eval] nested.err1.x.v.c.d: field not allowed: // ./reroot.cue:112:5 // ./reroot.cue:114:6 // ./reroot.cue:115:6 // ./reroot.cue:117:7 // ./reroot.cue:118:5 // ./reroot.cue:122:8 // ./reroot.cue:123:6 } } } #V: (_|_){ // [eval] c: (_|_){ // [eval] f: (_|_){ // [eval] nested.err1.x.#V.c.f: field not allowed: // ./reroot.cue:112:5 // ./reroot.cue:114:6 // ./reroot.cue:117:7 // ./reroot.cue:117:11 // ./reroot.cue:122:8 // ./reroot.cue:123:6 } g: (int){ 1 } d: (_|_){ // [eval] nested.err1.x.#V.c.d: field not allowed: // ./reroot.cue:112:5 // ./reroot.cue:114:6 // ./reroot.cue:117:7 // ./reroot.cue:118:5 // ./reroot.cue:122:8 // ./reroot.cue:123:6 } } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } v: (#struct){ c: (#struct){ f: (int){ 1 } d: (int){ 1 } } } #V: (#struct){ c: (#struct){ f: (int){ 1 } d: (int){ 1 } } } } #B: (#struct){ g: (int){ 1 } } } err2: (_|_){ // [eval] #A: (#struct){ b: (#struct){ } c: (#struct){ d: (int){ 1 } } } x: (_|_){ // [eval] b: (_|_){ // [eval] g: (_|_){ // [eval] nested.err2.x.b.g: field not allowed: // ./reroot.cue:128:6 // ./reroot.cue:136:5 // ./reroot.cue:137:8 } } c: (#struct){ g: (int){ 1 } d: (int){ 1 } } } } } inline: (struct){ #x: (#struct){ y: (#struct){ z?: (#struct){ name: (string){ string } } } } err1: (struct){ name: (string){ "a" } age1: (int){ 5 } } err2: (struct){ name: (string){ "a" } age2: (int){ 5 } } } mixInDef: (struct){ refInside: (struct){ #x: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } } a: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } } } refEdge: (struct){ #x: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } a: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } } refOutside: (struct){ #x: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } a: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } } } issue3601: (struct){ original: (struct){ out: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } #Transform: (#struct){ output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } #Patch: (#struct){ target: (#struct){ } output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } } originalNoShare: (struct){ out: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } #Transform: (#struct){ output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } #Patch: (#struct){ target: (#struct){ } output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } } reduced: (struct){ #X: (#struct){ a: (#struct){ b: (#struct){ c: (string){ "v1" } } } empty: (#struct){ } } original: (struct){ Y: (struct){ b: (struct){ c: (string){ "v1" } } } out: (struct){ b: (struct){ c: (string){ "v1" } } } } moreInlining: (struct){ out: (struct){ b: (struct){ c: (string){ "v1" } } } } noInline: (struct){ Y: (#struct){ a: (#struct){ b: (#struct){ c: (string){ "v1" } } } empty: (#struct){ } } Z: (#struct){ a: (#struct){ b: (#struct){ c: (string){ "v1" } } } empty: (#struct){ } } out: (struct){ b: (struct){ c: (string){ "v1" } } } } moreNesting: (struct){ #X: (#struct){ a: (#struct){ b: (#struct){ c: (#struct){ d: (string){ "v1" } } } } empty: (#struct){ } } Y: (struct){ c: (struct){ d: (string){ "v1" } } } Z: (struct){ c: (struct){ d: (string){ "v1" } } } } } } issue3332: (struct){ #def: (#struct){ field: (list){ list.MinItems(1) } } use: (#struct){ field: (#list){ 0: (string){ "value" } } } } } -- out/evalalpha -- Errors: inline.err1.age1: field not allowed: ./reroot.cue:145:3 inline.err2.age2: field not allowed: ./reroot.cue:149:3 nested.err1.x.b.f: field not allowed: ./reroot.cue:114:6 nested.err2.x.b.g: field not allowed: ./reroot.cue:137:8 patterns.shallow.and.p2.err.j: field not allowed: ./embed.cue:30:15 ./embed.cue:31:6 ./embed.cue:57:8 patterns.shallow.andEmbed.p2.err.j: field not allowed: ./embed.cue:30:15 ./embed.cue:31:6 ./embed.cue:76:8 patterns.shallow.single.err.j: field not allowed: ./embed.cue:30:15 ./embed.cue:38:8 patterns.shallow.and.p1.err.j: field not allowed: ./embed.cue:31:15 ./embed.cue:31:6 ./embed.cue:48:8 patterns.shallow.andEmbed.p1.err.j: field not allowed: ./embed.cue:31:15 ./embed.cue:31:6 ./embed.cue:67:8 patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: ./embed.cue:31:15 ./embed.cue:31:6 ./embed.cue:33:6 ./embed.cue:121:9 patterns.shallow.andOrEmbed.t2.ok2.p: field not allowed: ./embed.cue:31:15 ./embed.cue:30:6 ./embed.cue:132:4 ./embed.cue:141:8 patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: ./embed.cue:33:15 ./embed.cue:31:6 ./embed.cue:33:6 ./embed.cue:108:9 patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: ./embed.cue:33:15 ./embed.cue:31:6 ./embed.cue:33:6 ./embed.cue:135:9 patterns.shallow.indirect.p1.err1.j: field not allowed: ./embed.cue:146:15 ./embed.cue:152:10 patterns.shallow.indirect.p1.err2.j: field not allowed: ./embed.cue:146:15 ./embed.cue:155:10 patterns.shallow.indirect.p2.err1.j: field not allowed: ./embed.cue:146:15 ./embed.cue:166:10 patterns.shallow.indirect.p2.err2.j: field not allowed: ./embed.cue:146:15 ./embed.cue:169:10 patterns.shallow.indirect.p3.err1.j: field not allowed: ./embed.cue:146:15 ./embed.cue:179:10 patterns.shallow.indirect.p3.err2.j: field not allowed: ./embed.cue:146:15 ./embed.cue:182:10 patterns.shallow.indirect.p4.err1.j: field not allowed: ./embed.cue:146:15 ./embed.cue:194:10 patterns.shallow.indirect.p4.err2.j: field not allowed: ./embed.cue:146:15 ./embed.cue:197:10 patterns.nested.and.p2.err.x.y.j: field not allowed: ./embed.cue:206:21 ./embed.cue:207:12 ./embed.cue:233:14 patterns.nested.andEmbed.p2.err.x.y.j: field not allowed: ./embed.cue:206:21 ./embed.cue:207:12 ./embed.cue:252:14 patterns.nested.single.err.x.y.j: field not allowed: ./embed.cue:206:21 ./embed.cue:214:14 patterns.nested.and.p1.err.x.y.j: field not allowed: ./embed.cue:207:21 ./embed.cue:207:12 ./embed.cue:224:14 patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: ./embed.cue:207:21 ./embed.cue:207:12 ./embed.cue:243:14 patterns.nested.andOrEmbed.t1.p2.err1.x.y.j: field not allowed: ./embed.cue:207:21 ./embed.cue:207:12 ./embed.cue:209:12 ./embed.cue:297:15 patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: ./embed.cue:209:21 ./embed.cue:207:12 ./embed.cue:209:12 ./embed.cue:284:15 patterns.nested.andOrEmbed.t2.err1.x.y.j: field not allowed: ./embed.cue:209:21 ./embed.cue:207:12 ./embed.cue:209:12 ./embed.cue:311:15 patterns.nested.andOrEmbed.t2.ok2.x.y.p: field not allowed: ./embed.cue:209:21 ./embed.cue:206:12 ./embed.cue:209:12 ./embed.cue:317:14 patterns.nested.indirect.p1.err1.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:328:16 patterns.nested.indirect.p1.err2.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:331:16 patterns.nested.indirect.p2.err1.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:342:16 patterns.nested.indirect.p2.err2.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:345:16 patterns.nested.indirect.p3.err1.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:355:16 patterns.nested.indirect.p3.err2.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:358:16 patterns.nested.indirect.p4.err1.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:370:16 patterns.nested.indirect.p4.err2.x.y.j: field not allowed: ./embed.cue:322:21 ./embed.cue:373:16 a.q.e: field not allowed: ./in.cue:7:3 ./in.cue:15:3 issue852.a.Foo: field not allowed: ./in.cue:23:16 ./in.cue:28:5 indirect.embed.err1.b1.d: field not allowed: ./reroot.cue:67:7 ./reroot.cue:68:7 indirect.closed.err1.Y.a.e: field not allowed: ./reroot.cue:79:7 ./reroot.cue:75:7 nested.err1.x.#V.c.d: field not allowed: ./reroot.cue:122:8 ./reroot.cue:118:5 nested.err1.x.#V.c.f: field not allowed: ./reroot.cue:122:8 ./reroot.cue:114:6 nested.err1.x.b.g: field not allowed: ./reroot.cue:122:8 mixInDef.refInside.a.b.c.e.f: field not allowed: ./reroot.cue:160:15 ./reroot.cue:157:24 mixInDef.refEdge.a.c.e.f: field not allowed: ./reroot.cue:166:12 ./reroot.cue:163:21 mixInDef.refOutside.a.c.e.f: field not allowed: ./reroot.cue:172:12 ./reroot.cue:169:21 Result: (_|_){ // [eval] issue3325: (struct){ ok: (struct){ #Items: (#struct){ } #Base: (#struct){ name: (string){ "base" } type: (string){ string } items: (#struct){ } } #Extended: (#struct){ type: (string){ "extended" } items: (#struct){ "my-item": (#struct){ name: (string){ "my-item" } } } name: (string){ "base" } } broken: (#struct){ name: (string){ "base" } type: (string){ "extended" } items: (#struct){ "my-item": (#struct){ name: (string){ "my-item" } } } } works: (#struct){ type: (string){ "extended" } items: (#struct){ "my-item": (#struct){ name: (string){ "my-item" } } } name: (string){ "base" } } } } patterns: (_|_){ // [eval] shallow: (_|_){ // [eval] #a: (#struct){ } #b: (#struct){ } #c: (#struct){ } #d: (#struct){ } single: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.single.err.j: field not allowed: // ./embed.cue:30:15 // ./embed.cue:38:8 } } ok: (#struct){ k: (int){ 3 } } } and: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.and.p1.err.j: field not allowed: // ./embed.cue:31:15 // ./embed.cue:31:6 // ./embed.cue:48:8 } } ok: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.and.p2.err.j: field not allowed: // ./embed.cue:30:15 // ./embed.cue:31:6 // ./embed.cue:57:8 } } ok: (#struct){ k: (int){ 3 } } } } andEmbed: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andEmbed.p1.err.j: field not allowed: // ./embed.cue:31:15 // ./embed.cue:31:6 // ./embed.cue:67:8 } } ok: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] X: (#struct){ } err: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andEmbed.p2.err.j: field not allowed: // ./embed.cue:30:15 // ./embed.cue:31:6 // ./embed.cue:76:8 } } ok: (#struct){ k: (int){ 3 } } } } orEmbed: (struct){ p1: (struct){ X: (#struct){ } ok1: (#struct){ j: (int){ 3 } } ok2: (#struct){ k: (int){ 3 } } } p2: (struct){ X: (#struct){ } ok1: (#struct){ j: (int){ 3 } } ok2: (#struct){ k: (int){ 3 } } } } andOrEmbed: (_|_){ // [eval] t1: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: // ./embed.cue:33:15 // ./embed.cue:31:6 // ./embed.cue:33:6 // ./embed.cue:108:9 } } ok1: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: // ./embed.cue:31:15 // ./embed.cue:31:6 // ./embed.cue:33:6 // ./embed.cue:121:9 } } ok1: (#struct){ k: (int){ 3 } } } } t2: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: // ./embed.cue:33:15 // ./embed.cue:31:6 // ./embed.cue:33:6 // ./embed.cue:135:9 } } ok1: (#struct){ k: (int){ 3 } } ok2: (_|_){ // [eval] p: (_|_){ // [eval] patterns.shallow.andOrEmbed.t2.ok2.p: field not allowed: // ./embed.cue:31:15 // ./embed.cue:30:6 // ./embed.cue:132:4 // ./embed.cue:141:8 } } } } indirect: (_|_){ // [eval] a: (struct){ } #a: (#struct){ } p1: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p1.err1.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:152:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p1.err2.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:155:10 } } ok: (#struct){ k: (int){ 3 } } } p2: (_|_){ // [eval] #a: (#struct){ } X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p2.err1.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:166:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p2.err2.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:169:10 } } ok: (#struct){ k: (int){ 3 } } } p3: (_|_){ // [eval] X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p3.err1.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:179:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p3.err2.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:182:10 } } ok: (#struct){ k: (int){ 3 } } } p4: (_|_){ // [eval] #a: (#struct){ } X: (#struct){ } err1: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p4.err1.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:194:10 } } err2: (_|_){ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p4.err2.j: field not allowed: // ./embed.cue:146:15 // ./embed.cue:197:10 } } ok: (#struct){ k: (int){ 3 } } } } } nested: (_|_){ // [eval] #a: (#struct){ x: (#struct){ y: (#struct){ } } } #b: (#struct){ x: (#struct){ y: (#struct){ } } } #c: (#struct){ x: (#struct){ y: (#struct){ } } } #d: (#struct){ x: (#struct){ y: (#struct){ } } } single: (_|_){ // [eval] X: ~(patterns.nested.#a) err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.single.err.x.y.j: field not allowed: // ./embed.cue:206:21 // ./embed.cue:214:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } and: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.and.p1.err.x.y.j: field not allowed: // ./embed.cue:207:21 // ./embed.cue:207:12 // ./embed.cue:224:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.and.p2.err.x.y.j: field not allowed: // ./embed.cue:206:21 // ./embed.cue:207:12 // ./embed.cue:233:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } andEmbed: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: // ./embed.cue:207:21 // ./embed.cue:207:12 // ./embed.cue:243:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andEmbed.p2.err.x.y.j: field not allowed: // ./embed.cue:206:21 // ./embed.cue:207:12 // ./embed.cue:252:14 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } orEmbed: (struct){ p1: (struct){ X: (#struct){ x: (#struct){ y: (#struct){ } } } ok1: (#struct){ x: (#struct){ y: (#struct){ j: (int){ 3 } } } } ok2: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (struct){ X: (#struct){ x: (#struct){ y: (#struct){ } } } ok1: (#struct){ x: (#struct){ y: (#struct){ j: (int){ 3 } } } } ok2: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } andOrEmbed: (_|_){ // [eval] t1: (_|_){ // [eval] p1: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: // ./embed.cue:209:21 // ./embed.cue:207:12 // ./embed.cue:209:12 // ./embed.cue:284:15 } } } } ok1: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t1.p2.err1.x.y.j: field not allowed: // ./embed.cue:207:21 // ./embed.cue:207:12 // ./embed.cue:209:12 // ./embed.cue:297:15 } } } } ok1: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } t2: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t2.err1.x.y.j: field not allowed: // ./embed.cue:209:21 // ./embed.cue:207:12 // ./embed.cue:209:12 // ./embed.cue:311:15 } } } } ok1: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } ok2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] p: (_|_){ // [eval] patterns.nested.andOrEmbed.t2.ok2.x.y.p: field not allowed: // ./embed.cue:209:21 // ./embed.cue:206:12 // ./embed.cue:209:12 // ./embed.cue:317:14 } } } } } } indirect: (_|_){ // [eval] a: (struct){ x: (struct){ y: (struct){ } } } #a: (#struct){ x: (#struct){ y: (#struct){ } } } p1: (_|_){ // [eval] X: ~(patterns.nested.indirect.#a) err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p1.err1.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:328:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p1.err2.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:331:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p2: (_|_){ // [eval] #a: (#struct){ x: (#struct){ y: (#struct){ } } } X: ~(patterns.nested.indirect.p2.#a) err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p2.err1.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:342:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p2.err2.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:345:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p3: (_|_){ // [eval] X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p3.err1.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:355:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p3.err2.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:358:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } p4: (_|_){ // [eval] #a: (#struct){ x: (#struct){ y: (#struct){ } } } X: (#struct){ x: (#struct){ y: (#struct){ } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p4.err1.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:370:16 } } } } err2: (_|_){ // [eval] x: (_|_){ // [eval] y: (_|_){ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p4.err2.x.y.j: field not allowed: // ./embed.cue:322:21 // ./embed.cue:373:16 } } } } ok: (#struct){ x: (#struct){ y: (#struct){ k: (int){ 3 } } } } } } } } #E: (#struct){ c: (int){ int } } #A: (#struct){ b: (int){ int } q: (#struct){ d: (int){ int } c: (int){ int } } } a: (_|_){ // [eval] b: (int){ 3 } q: (_|_){ // [eval] c: (int){ 2 } e: (_|_){ // [eval] a.q.e: field not allowed: // ./in.cue:7:3 // ./in.cue:15:3 } d: (int){ int } } } issue852: (_|_){ // [eval] issue852.a.Foo: field not allowed: // ./in.cue:23:16 // ./in.cue:28:5 #A: (#struct){ } a: (_|_){ // [eval] Foo: (_|_){ // [eval] issue852.a.Foo: field not allowed: // ./in.cue:23:16 // ./in.cue:28:5 } } } dynamic: (struct){ #D: (#struct){ key: (string){ "foo" } foo: (int){ int } } d: (#struct){ foo: (int){ 3 } key: (string){ "foo" } } } issue3330: (struct){ let: (struct){ ok: (struct){ #struct: (#struct){ let empty#1 = (#struct){ } field: (#struct){ n: (int){ 3 } } } out: (#list){ 0: ~(issue3330.let.ok.#struct) } } } matthew: (struct){ ok1: (struct){ #struct: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } } ok2: (struct){ #struct: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out: ~(issue3330.matthew.ok2.#struct) out2: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } } } } issue3331: (struct){ original: (struct){ ok: (#list){ #A: (#struct){ let b#2 = (#struct){ } c: (#struct){ d: (int){ 1 } } } 0: ~(issue3331.original.ok.#A) } } variant1: (struct){ ok: (#list){ #A: (#struct){ let b#3 = (#struct){ } c: (#struct){ d: (int){ 1 } } } 0: (#list){ 0: ~(issue3331.variant1.ok.#A) } } } } indirect: (_|_){ // [eval] embed: (_|_){ // [eval] err1: (_|_){ // [eval] #A: (#struct){ x: (#struct){ a: (#struct){ b: (int){ 1 } c: (int){ 2 } } } zx: ~(indirect.embed.err1.#A.x.a) } #x: (#struct){ a: (#struct){ b: (int){ 1 } } } #y: (#struct){ a: (#struct){ c: (int){ 2 } } } b: ~(indirect.embed.err1.#A) b1: (_|_){ // [eval] d: (_|_){ // [eval] indirect.embed.err1.b1.d: field not allowed: // ./reroot.cue:67:7 // ./reroot.cue:68:7 } b: (int){ 1 } c: (int){ 2 } } } } closed: (_|_){ // [eval] err1: (_|_){ // [eval] X: (struct){ a: (struct){ e: (int){ 1 } } b: (struct){ } } Y: (_|_){ // [eval] b: (#struct){ } c: (#struct){ } a: (_|_){ // [eval] e: (_|_){ // [eval] indirect.closed.err1.Y.a.e: field not allowed: // ./reroot.cue:79:7 // ./reroot.cue:75:7 } } } #X: (#struct){ } } } } nested: (_|_){ // [eval] ok1: (struct){ #A: (#struct){ b: (#struct){ } #B: (#struct){ c: (#struct){ d: (int){ 1 } } } } x: ~(nested.ok1.#A) } embed: (struct){ ok: (struct){ x: ~(nested.embed.ok.#A) #A: (#struct){ d: (#struct){ e: (int){ int } } b: (#struct){ } } k: (struct){ d: (struct){ e: (int){ int } } b: (struct){ } } } } err1: (_|_){ // [eval] x: (_|_){ // [eval] b: (_|_){ // [eval] f: (_|_){ // [eval] nested.err1.x.b.f: field not allowed: // ./reroot.cue:114:6 } g: (_|_){ // [eval] nested.err1.x.b.g: field not allowed: // ./reroot.cue:122:8 } } v: ~(nested.err1.x.#V) #V: (_|_){ // [eval] c: (_|_){ // [eval] d: (_|_){ // [eval] nested.err1.x.#V.c.d: field not allowed: // ./reroot.cue:122:8 // ./reroot.cue:118:5 } f: (_|_){ // [eval] nested.err1.x.#V.c.f: field not allowed: // ./reroot.cue:122:8 // ./reroot.cue:114:6 } g: (int){ 1 } } } } #A: (#struct){ b: (#struct){ f: (int){ 1 } } v: ~(nested.err1.#A.#V) #V: (#struct){ c: (#struct){ d: (int){ 1 } f: (int){ 1 } } } } #B: (#struct){ g: (int){ 1 } } } err2: (_|_){ // [eval] #A: (#struct){ b: (#struct){ } c: (#struct){ d: (int){ 1 } } } x: (_|_){ // [eval] b: (_|_){ // [eval] g: (_|_){ // [eval] nested.err2.x.b.g: field not allowed: // ./reroot.cue:137:8 } } c: (#struct){ d: (int){ 1 } g: (int){ 1 } } } } } inline: (_|_){ // [eval] #x: (#struct){ y: (#struct){ z?: (#struct){ name: (string){ string } } } } err1: (_|_){ // [eval] name: (string){ "a" } age1: (_|_){ // [eval] inline.err1.age1: field not allowed: // ./reroot.cue:145:3 } } err2: (_|_){ // [eval] name: (string){ "a" } age2: (_|_){ // [eval] inline.err2.age2: field not allowed: // ./reroot.cue:149:3 } } } mixInDef: (_|_){ // [eval] refInside: (_|_){ // [eval] #x: (#struct){ b: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } } a: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] d: (#struct){ } e: (_|_){ // [eval] f: (_|_){ // [eval] mixInDef.refInside.a.b.c.e.f: field not allowed: // ./reroot.cue:160:15 // ./reroot.cue:157:24 } } } } } } refEdge: (_|_){ // [eval] #x: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } a: (_|_){ // [eval] c: (_|_){ // [eval] d: (#struct){ } e: (_|_){ // [eval] f: (_|_){ // [eval] mixInDef.refEdge.a.c.e.f: field not allowed: // ./reroot.cue:166:12 // ./reroot.cue:163:21 } } } } } refOutside: (_|_){ // [eval] #x: (#struct){ c: (#struct){ d: (#struct){ } e: (#struct){ f: (#struct){ } } } } a: (_|_){ // [eval] c: (_|_){ // [eval] d: (#struct){ } e: (_|_){ // [eval] f: (_|_){ // [eval] mixInDef.refOutside.a.c.e.f: field not allowed: // ./reroot.cue:172:12 // ./reroot.cue:169:21 } } } } } } issue3601: (struct){ original: (struct){ out: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } #Transform: (#struct){ output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } #Patch: (#struct){ target: (#struct){ } output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } } originalNoShare: (struct){ out: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } #Transform: (#struct){ output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } #Patch: (#struct){ target: (#struct){ } output: (#struct){ foo: (#struct){ final: (#struct){ version: (string){ "v1" } } } } } } reduced: (struct){ #X: (#struct){ a: (#struct){ b: (#struct){ c: (string){ "v1" } } } empty: (#struct){ } } original: (struct){ Y: (#struct){ b: (#struct){ c: (string){ "v1" } } } out: (struct){ b: (struct){ c: (string){ "v1" } } } } moreInlining: (struct){ out: (#struct){ b: (#struct){ c: (string){ "v1" } } } } noInline: (struct){ Y: (#struct){ a: (#struct){ b: (#struct){ c: (string){ "v1" } } } empty: (#struct){ } } Z: (#struct){ a: (#struct){ b: (#struct){ c: (string){ "v1" } } } empty: (#struct){ } } out: (#struct){ b: (#struct){ c: (string){ "v1" } } } } moreNesting: (struct){ #X: (#struct){ a: (#struct){ b: (#struct){ c: (#struct){ d: (string){ "v1" } } } } empty: (#struct){ } } Y: (#struct){ c: (#struct){ d: (string){ "v1" } } } Z: (struct){ c: (struct){ d: (string){ "v1" } } } } } } issue3332: (struct){ #def: (#struct){ field: (list){ list.MinItems(1) } } use: (#struct){ field: (#list){ 0: (string){ "value" } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,310 +1,167 @@ Errors: -a.q.e: field not allowed: - ./in.cue:1:5 - ./in.cue:6:5 - ./in.cue:7:3 - ./in.cue:11:4 - ./in.cue:15:3 -indirect.closed.err1.Y.a.e: field not allowed: - ./reroot.cue:73:7 - ./reroot.cue:74:7 - ./reroot.cue:75:7 - ./reroot.cue:77:6 - ./reroot.cue:79:7 - ./reroot.cue:80:7 - ./reroot.cue:82:7 -issue852.a.Foo: field not allowed: - ./in.cue:22:6 - ./in.cue:26:5 - ./in.cue:28:5 -nested.err1.x.#V.c.d: field not allowed: - ./reroot.cue:112:5 - ./reroot.cue:114:6 - ./reroot.cue:117:7 - ./reroot.cue:118:5 - ./reroot.cue:122:8 - ./reroot.cue:123:6 -nested.err1.x.#V.c.f: field not allowed: - ./reroot.cue:112:5 - ./reroot.cue:114:6 - ./reroot.cue:117:7 - ./reroot.cue:117:11 - ./reroot.cue:122:8 - ./reroot.cue:123:6 +inline.err1.age1: field not allowed: + ./reroot.cue:145:3 +inline.err2.age2: field not allowed: + ./reroot.cue:149:3 nested.err1.x.b.f: field not allowed: - ./reroot.cue:112:5 - ./reroot.cue:114:6 - ./reroot.cue:122:8 - ./reroot.cue:123:6 -nested.err1.x.b.g: field not allowed: - ./reroot.cue:112:5 - ./reroot.cue:114:6 - ./reroot.cue:122:8 - ./reroot.cue:123:6 -nested.err1.x.v.c.d: field not allowed: - ./reroot.cue:112:5 - ./reroot.cue:114:6 - ./reroot.cue:115:6 - ./reroot.cue:117:7 - ./reroot.cue:118:5 - ./reroot.cue:122:8 - ./reroot.cue:123:6 -nested.err1.x.v.c.f: field not allowed: - ./reroot.cue:112:5 - ./reroot.cue:114:6 - ./reroot.cue:115:6 - ./reroot.cue:117:7 - ./reroot.cue:117:11 - ./reroot.cue:122:8 - ./reroot.cue:123:6 + ./reroot.cue:114:6 nested.err2.x.b.g: field not allowed: - ./reroot.cue:128:6 - ./reroot.cue:136:5 ./reroot.cue:137:8 -patterns.nested.and.p1.err.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:221:6 - ./embed.cue:221:11 - ./embed.cue:223:8 - ./embed.cue:224:14 +patterns.shallow.and.p2.err.j: field not allowed: + ./embed.cue:30:15 + ./embed.cue:31:6 + ./embed.cue:57:8 +patterns.shallow.andEmbed.p2.err.j: field not allowed: + ./embed.cue:30:15 + ./embed.cue:31:6 + ./embed.cue:76:8 +patterns.shallow.single.err.j: field not allowed: + ./embed.cue:30:15 + ./embed.cue:38:8 +patterns.shallow.and.p1.err.j: field not allowed: + ./embed.cue:31:15 + ./embed.cue:31:6 + ./embed.cue:48:8 +patterns.shallow.andEmbed.p1.err.j: field not allowed: + ./embed.cue:31:15 + ./embed.cue:31:6 + ./embed.cue:67:8 +patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: + ./embed.cue:31:15 + ./embed.cue:31:6 + ./embed.cue:33:6 + ./embed.cue:121:9 +patterns.shallow.andOrEmbed.t2.ok2.p: field not allowed: + ./embed.cue:31:15 + ./embed.cue:30:6 + ./embed.cue:132:4 + ./embed.cue:141:8 +patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: + ./embed.cue:33:15 + ./embed.cue:31:6 + ./embed.cue:33:6 + ./embed.cue:108:9 +patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: + ./embed.cue:33:15 + ./embed.cue:31:6 + ./embed.cue:33:6 + ./embed.cue:135:9 +patterns.shallow.indirect.p1.err1.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:152:10 +patterns.shallow.indirect.p1.err2.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:155:10 +patterns.shallow.indirect.p2.err1.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:166:10 +patterns.shallow.indirect.p2.err2.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:169:10 +patterns.shallow.indirect.p3.err1.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:179:10 +patterns.shallow.indirect.p3.err2.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:182:10 +patterns.shallow.indirect.p4.err1.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:194:10 +patterns.shallow.indirect.p4.err2.j: field not allowed: + ./embed.cue:146:15 + ./embed.cue:197:10 patterns.nested.and.p2.err.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:231:6 - ./embed.cue:231:11 - ./embed.cue:232:8 + ./embed.cue:206:21 + ./embed.cue:207:12 ./embed.cue:233:14 -patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:240:8 - ./embed.cue:240:13 - ./embed.cue:242:8 - ./embed.cue:243:14 patterns.nested.andEmbed.p2.err.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:250:8 - ./embed.cue:250:13 - ./embed.cue:251:8 + ./embed.cue:206:21 + ./embed.cue:207:12 ./embed.cue:252:14 -patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:208:12 - ./embed.cue:209:12 - ./embed.cue:280:4 - ./embed.cue:280:9 - ./embed.cue:281:4 - ./embed.cue:281:9 - ./embed.cue:283:9 - ./embed.cue:284:15 +patterns.nested.single.err.x.y.j: field not allowed: + ./embed.cue:206:21 + ./embed.cue:214:14 +patterns.nested.and.p1.err.x.y.j: field not allowed: + ./embed.cue:207:21 + ./embed.cue:207:12 + ./embed.cue:224:14 +patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: + ./embed.cue:207:21 + ./embed.cue:207:12 + ./embed.cue:243:14 patterns.nested.andOrEmbed.t1.p2.err1.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:208:12 - ./embed.cue:209:12 - ./embed.cue:293:4 - ./embed.cue:293:9 - ./embed.cue:294:4 - ./embed.cue:294:9 - ./embed.cue:296:9 + ./embed.cue:207:21 + ./embed.cue:207:12 + ./embed.cue:209:12 ./embed.cue:297:15 +patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: + ./embed.cue:209:21 + ./embed.cue:207:12 + ./embed.cue:209:12 + ./embed.cue:284:15 patterns.nested.andOrEmbed.t2.err1.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:208:12 - ./embed.cue:209:12 - ./embed.cue:306:4 - ./embed.cue:306:9 - ./embed.cue:307:4 - ./embed.cue:307:9 - ./embed.cue:310:9 + ./embed.cue:209:21 + ./embed.cue:207:12 + ./embed.cue:209:12 ./embed.cue:311:15 patterns.nested.andOrEmbed.t2.ok2.x.y.p: field not allowed: - ./embed.cue:206:12 - ./embed.cue:207:12 - ./embed.cue:208:12 - ./embed.cue:209:12 - ./embed.cue:306:4 - ./embed.cue:306:9 - ./embed.cue:307:4 - ./embed.cue:307:9 - ./embed.cue:316:8 + ./embed.cue:209:21 + ./embed.cue:206:12 + ./embed.cue:209:12 ./embed.cue:317:14 patterns.nested.indirect.p1.err1.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:323:7 - ./embed.cue:326:7 - ./embed.cue:327:10 + ./embed.cue:322:21 ./embed.cue:328:16 patterns.nested.indirect.p1.err2.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:323:7 - ./embed.cue:326:7 - ./embed.cue:330:10 + ./embed.cue:322:21 ./embed.cue:331:16 patterns.nested.indirect.p2.err1.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:338:8 - ./embed.cue:339:7 - ./embed.cue:341:10 + ./embed.cue:322:21 ./embed.cue:342:16 patterns.nested.indirect.p2.err2.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:338:8 - ./embed.cue:339:7 - ./embed.cue:344:10 + ./embed.cue:322:21 ./embed.cue:345:16 patterns.nested.indirect.p3.err1.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:323:7 - ./embed.cue:352:7 - ./embed.cue:354:10 + ./embed.cue:322:21 ./embed.cue:355:16 patterns.nested.indirect.p3.err2.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:323:7 - ./embed.cue:352:7 - ./embed.cue:357:10 + ./embed.cue:322:21 ./embed.cue:358:16 patterns.nested.indirect.p4.err1.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:365:8 - ./embed.cue:366:7 - ./embed.cue:369:10 + ./embed.cue:322:21 ./embed.cue:370:16 patterns.nested.indirect.p4.err2.x.y.j: field not allowed: - ./embed.cue:322:12 - ./embed.cue:365:8 - ./embed.cue:366:7 - ./embed.cue:372:10 + ./embed.cue:322:21 ./embed.cue:373:16 -patterns.nested.single.err.x.y.j: field not allowed: - ./embed.cue:206:12 - ./embed.cue:212:6 - ./embed.cue:213:8 - ./embed.cue:214:14 -patterns.shallow.and.p1.err.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:45:6 - ./embed.cue:45:11 - ./embed.cue:47:8 - ./embed.cue:48:8 -patterns.shallow.and.p2.err.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:55:6 - ./embed.cue:55:11 - ./embed.cue:56:8 - ./embed.cue:57:8 -patterns.shallow.andEmbed.p1.err.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:64:6 - ./embed.cue:64:8 - ./embed.cue:64:13 - ./embed.cue:66:8 - ./embed.cue:67:8 -patterns.shallow.andEmbed.p2.err.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:74:6 - ./embed.cue:74:8 - ./embed.cue:74:13 - ./embed.cue:75:8 - ./embed.cue:76:8 -patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:32:6 - ./embed.cue:33:6 - ./embed.cue:103:6 - ./embed.cue:104:4 - ./embed.cue:104:9 - ./embed.cue:105:4 - ./embed.cue:105:9 - ./embed.cue:107:9 - ./embed.cue:108:9 -patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:32:6 - ./embed.cue:33:6 - ./embed.cue:116:6 - ./embed.cue:117:4 - ./embed.cue:117:9 - ./embed.cue:118:4 - ./embed.cue:118:9 - ./embed.cue:120:9 - ./embed.cue:121:9 -patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:31:6 - ./embed.cue:32:6 - ./embed.cue:33:6 - ./embed.cue:129:6 - ./embed.cue:130:4 - ./embed.cue:130:9 - ./embed.cue:131:4 - ./embed.cue:131:9 - ./embed.cue:134:9 - ./embed.cue:135:9 -patterns.shallow.indirect.p1.err1.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:147:7 - ./embed.cue:150:7 - ./embed.cue:151:10 - ./embed.cue:152:10 -patterns.shallow.indirect.p1.err2.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:147:7 - ./embed.cue:150:7 - ./embed.cue:154:10 - ./embed.cue:155:10 -patterns.shallow.indirect.p2.err1.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:162:8 - ./embed.cue:163:7 - ./embed.cue:165:10 - ./embed.cue:166:10 -patterns.shallow.indirect.p2.err2.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:162:8 - ./embed.cue:163:7 - ./embed.cue:168:10 - ./embed.cue:169:10 -patterns.shallow.indirect.p3.err1.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:147:7 - ./embed.cue:176:7 - ./embed.cue:178:10 - ./embed.cue:179:10 -patterns.shallow.indirect.p3.err2.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:147:7 - ./embed.cue:176:7 - ./embed.cue:181:10 - ./embed.cue:182:10 -patterns.shallow.indirect.p4.err1.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:189:8 - ./embed.cue:190:7 - ./embed.cue:193:10 - ./embed.cue:194:10 -patterns.shallow.indirect.p4.err2.j: field not allowed: - ./embed.cue:146:6 - ./embed.cue:189:8 - ./embed.cue:190:7 - ./embed.cue:196:10 - ./embed.cue:197:10 -patterns.shallow.single.err.j: field not allowed: - ./embed.cue:30:6 - ./embed.cue:36:6 - ./embed.cue:37:8 - ./embed.cue:38:8 +a.q.e: field not allowed: + ./in.cue:7:3 + ./in.cue:15:3 +issue852.a.Foo: field not allowed: + ./in.cue:23:16 + ./in.cue:28:5 +indirect.embed.err1.b1.d: field not allowed: + ./reroot.cue:67:7 + ./reroot.cue:68:7 +indirect.closed.err1.Y.a.e: field not allowed: + ./reroot.cue:79:7 + ./reroot.cue:75:7 +nested.err1.x.#V.c.d: field not allowed: + ./reroot.cue:122:8 + ./reroot.cue:118:5 +nested.err1.x.#V.c.f: field not allowed: + ./reroot.cue:122:8 + ./reroot.cue:114:6 +nested.err1.x.b.g: field not allowed: + ./reroot.cue:122:8 +mixInDef.refInside.a.b.c.e.f: field not allowed: + ./reroot.cue:160:15 + ./reroot.cue:157:24 +mixInDef.refEdge.a.c.e.f: field not allowed: + ./reroot.cue:166:12 + ./reroot.cue:163:21 +mixInDef.refOutside.a.c.e.f: field not allowed: + ./reroot.cue:172:12 + ./reroot.cue:169:21 Result: (_|_){ @@ -320,13 +177,13 @@ } } #Extended: (#struct){ - name: (string){ "base" } - type: (string){ "extended" } - items: (#struct){ - "my-item": (#struct){ - name: (string){ "my-item" } - } - } + type: (string){ "extended" } + items: (#struct){ + "my-item": (#struct){ + name: (string){ "my-item" } + } + } + name: (string){ "base" } } broken: (#struct){ name: (string){ "base" } @@ -338,13 +195,13 @@ } } works: (#struct){ - name: (string){ "base" } - type: (string){ "extended" } - items: (#struct){ - "my-item": (#struct){ - name: (string){ "my-item" } - } - } + type: (string){ "extended" } + items: (#struct){ + "my-item": (#struct){ + name: (string){ "my-item" } + } + } + name: (string){ "base" } } } } @@ -368,9 +225,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.single.err.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:36:6 - // ./embed.cue:37:8 + // ./embed.cue:30:15 // ./embed.cue:38:8 } } @@ -388,11 +243,8 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.and.p1.err.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:45:6 - // ./embed.cue:45:11 - // ./embed.cue:47:8 + // ./embed.cue:31:15 + // ./embed.cue:31:6 // ./embed.cue:48:8 } } @@ -408,11 +260,8 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.and.p2.err.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:55:6 - // ./embed.cue:55:11 - // ./embed.cue:56:8 + // ./embed.cue:30:15 + // ./embed.cue:31:6 // ./embed.cue:57:8 } } @@ -431,12 +280,8 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.andEmbed.p1.err.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:64:6 - // ./embed.cue:64:8 - // ./embed.cue:64:13 - // ./embed.cue:66:8 + // ./embed.cue:31:15 + // ./embed.cue:31:6 // ./embed.cue:67:8 } } @@ -452,12 +297,8 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.andEmbed.p2.err.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:74:6 - // ./embed.cue:74:8 - // ./embed.cue:74:13 - // ./embed.cue:75:8 + // ./embed.cue:30:15 + // ./embed.cue:31:6 // ./embed.cue:76:8 } } @@ -500,16 +341,9 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t1.p1.err1.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:32:6 - // ./embed.cue:33:6 - // ./embed.cue:103:6 - // ./embed.cue:104:4 - // ./embed.cue:104:9 - // ./embed.cue:105:4 - // ./embed.cue:105:9 - // ./embed.cue:107:9 + // ./embed.cue:33:15 + // ./embed.cue:31:6 + // ./embed.cue:33:6 // ./embed.cue:108:9 } } @@ -525,16 +359,9 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t1.p2.err1.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:32:6 - // ./embed.cue:33:6 - // ./embed.cue:116:6 - // ./embed.cue:117:4 - // ./embed.cue:117:9 - // ./embed.cue:118:4 - // ./embed.cue:118:9 - // ./embed.cue:120:9 + // ./embed.cue:31:15 + // ./embed.cue:31:6 + // ./embed.cue:33:6 // ./embed.cue:121:9 } } @@ -551,16 +378,9 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.andOrEmbed.t2.err1.j: field not allowed: - // ./embed.cue:30:6 - // ./embed.cue:31:6 - // ./embed.cue:32:6 + // ./embed.cue:33:15 + // ./embed.cue:31:6 // ./embed.cue:33:6 - // ./embed.cue:129:6 - // ./embed.cue:130:4 - // ./embed.cue:130:9 - // ./embed.cue:131:4 - // ./embed.cue:131:9 - // ./embed.cue:134:9 // ./embed.cue:135:9 } } @@ -567,8 +387,15 @@ ok1: (#struct){ k: (int){ 3 } } - ok2: (#struct){ - p: (int){ 3 } + ok2: (_|_){ + // [eval] + p: (_|_){ + // [eval] patterns.shallow.andOrEmbed.t2.ok2.p: field not allowed: + // ./embed.cue:31:15 + // ./embed.cue:30:6 + // ./embed.cue:132:4 + // ./embed.cue:141:8 + } } } } @@ -586,10 +413,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p1.err1.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:147:7 - // ./embed.cue:150:7 - // ./embed.cue:151:10 + // ./embed.cue:146:15 // ./embed.cue:152:10 } } @@ -597,10 +421,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p1.err2.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:147:7 - // ./embed.cue:150:7 - // ./embed.cue:154:10 + // ./embed.cue:146:15 // ./embed.cue:155:10 } } @@ -618,10 +439,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p2.err1.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:162:8 - // ./embed.cue:163:7 - // ./embed.cue:165:10 + // ./embed.cue:146:15 // ./embed.cue:166:10 } } @@ -629,10 +447,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p2.err2.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:162:8 - // ./embed.cue:163:7 - // ./embed.cue:168:10 + // ./embed.cue:146:15 // ./embed.cue:169:10 } } @@ -648,10 +463,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p3.err1.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:147:7 - // ./embed.cue:176:7 - // ./embed.cue:178:10 + // ./embed.cue:146:15 // ./embed.cue:179:10 } } @@ -659,10 +471,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p3.err2.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:147:7 - // ./embed.cue:176:7 - // ./embed.cue:181:10 + // ./embed.cue:146:15 // ./embed.cue:182:10 } } @@ -680,10 +489,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p4.err1.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:189:8 - // ./embed.cue:190:7 - // ./embed.cue:193:10 + // ./embed.cue:146:15 // ./embed.cue:194:10 } } @@ -691,10 +497,7 @@ // [eval] j: (_|_){ // [eval] patterns.shallow.indirect.p4.err2.j: field not allowed: - // ./embed.cue:146:6 - // ./embed.cue:189:8 - // ./embed.cue:190:7 - // ./embed.cue:196:10 + // ./embed.cue:146:15 // ./embed.cue:197:10 } } @@ -732,12 +535,7 @@ } single: (_|_){ // [eval] - X: (#struct){ - x: (#struct){ - y: (#struct){ - } - } - } + X: ~(patterns.nested.#a) err: (_|_){ // [eval] x: (_|_){ @@ -746,9 +544,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.single.err.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:212:6 - // ./embed.cue:213:8 + // ./embed.cue:206:21 // ./embed.cue:214:14 } } @@ -780,11 +576,8 @@ // [eval] j: (_|_){ // [eval] patterns.nested.and.p1.err.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:221:6 - // ./embed.cue:221:11 - // ./embed.cue:223:8 + // ./embed.cue:207:21 + // ./embed.cue:207:12 // ./embed.cue:224:14 } } @@ -814,11 +607,8 @@ // [eval] j: (_|_){ // [eval] patterns.nested.and.p2.err.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:231:6 - // ./embed.cue:231:11 - // ./embed.cue:232:8 + // ./embed.cue:206:21 + // ./embed.cue:207:12 // ./embed.cue:233:14 } } @@ -851,11 +641,8 @@ // [eval] j: (_|_){ // [eval] patterns.nested.andEmbed.p1.err.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:240:8 - // ./embed.cue:240:13 - // ./embed.cue:242:8 + // ./embed.cue:207:21 + // ./embed.cue:207:12 // ./embed.cue:243:14 } } @@ -885,11 +672,8 @@ // [eval] j: (_|_){ // [eval] patterns.nested.andEmbed.p2.err.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:250:8 - // ./embed.cue:250:13 - // ./embed.cue:251:8 + // ./embed.cue:206:21 + // ./embed.cue:207:12 // ./embed.cue:252:14 } } @@ -970,15 +754,9 @@ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t1.p1.err1.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:208:12 - // ./embed.cue:209:12 - // ./embed.cue:280:4 - // ./embed.cue:280:9 - // ./embed.cue:281:4 - // ./embed.cue:281:9 - // ./embed.cue:283:9 + // ./embed.cue:209:21 + // ./embed.cue:207:12 + // ./embed.cue:209:12 // ./embed.cue:284:15 } } @@ -1008,15 +786,9 @@ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t1.p2.err1.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:208:12 - // ./embed.cue:209:12 - // ./embed.cue:293:4 - // ./embed.cue:293:9 - // ./embed.cue:294:4 - // ./embed.cue:294:9 - // ./embed.cue:296:9 + // ./embed.cue:207:21 + // ./embed.cue:207:12 + // ./embed.cue:209:12 // ./embed.cue:297:15 } } @@ -1047,15 +819,9 @@ // [eval] j: (_|_){ // [eval] patterns.nested.andOrEmbed.t2.err1.x.y.j: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:208:12 - // ./embed.cue:209:12 - // ./embed.cue:306:4 - // ./embed.cue:306:9 - // ./embed.cue:307:4 - // ./embed.cue:307:9 - // ./embed.cue:310:9 + // ./embed.cue:209:21 + // ./embed.cue:207:12 + // ./embed.cue:209:12 // ./embed.cue:311:15 } } @@ -1076,15 +842,9 @@ // [eval] p: (_|_){ // [eval] patterns.nested.andOrEmbed.t2.ok2.x.y.p: field not allowed: - // ./embed.cue:206:12 - // ./embed.cue:207:12 - // ./embed.cue:208:12 - // ./embed.cue:209:12 - // ./embed.cue:306:4 - // ./embed.cue:306:9 - // ./embed.cue:307:4 - // ./embed.cue:307:9 - // ./embed.cue:316:8 + // ./embed.cue:209:21 + // ./embed.cue:206:12 + // ./embed.cue:209:12 // ./embed.cue:317:14 } } @@ -1108,12 +868,7 @@ } p1: (_|_){ // [eval] - X: (#struct){ - x: (#struct){ - y: (#struct){ - } - } - } + X: ~(patterns.nested.indirect.#a) err1: (_|_){ // [eval] x: (_|_){ @@ -1122,10 +877,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p1.err1.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:323:7 - // ./embed.cue:326:7 - // ./embed.cue:327:10 + // ./embed.cue:322:21 // ./embed.cue:328:16 } } @@ -1139,10 +891,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p1.err2.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:323:7 - // ./embed.cue:326:7 - // ./embed.cue:330:10 + // ./embed.cue:322:21 // ./embed.cue:331:16 } } @@ -1164,12 +913,7 @@ } } } - X: (#struct){ - x: (#struct){ - y: (#struct){ - } - } - } + X: ~(patterns.nested.indirect.p2.#a) err1: (_|_){ // [eval] x: (_|_){ @@ -1178,10 +922,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p2.err1.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:338:8 - // ./embed.cue:339:7 - // ./embed.cue:341:10 + // ./embed.cue:322:21 // ./embed.cue:342:16 } } @@ -1195,10 +936,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p2.err2.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:338:8 - // ./embed.cue:339:7 - // ./embed.cue:344:10 + // ./embed.cue:322:21 // ./embed.cue:345:16 } } @@ -1228,10 +966,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p3.err1.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:323:7 - // ./embed.cue:352:7 - // ./embed.cue:354:10 + // ./embed.cue:322:21 // ./embed.cue:355:16 } } @@ -1245,10 +980,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p3.err2.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:323:7 - // ./embed.cue:352:7 - // ./embed.cue:357:10 + // ./embed.cue:322:21 // ./embed.cue:358:16 } } @@ -1284,10 +1016,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p4.err1.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:365:8 - // ./embed.cue:366:7 - // ./embed.cue:369:10 + // ./embed.cue:322:21 // ./embed.cue:370:16 } } @@ -1301,10 +1030,7 @@ // [eval] j: (_|_){ // [eval] patterns.nested.indirect.p4.err2.x.y.j: field not allowed: - // ./embed.cue:322:12 - // ./embed.cue:365:8 - // ./embed.cue:366:7 - // ./embed.cue:372:10 + // ./embed.cue:322:21 // ./embed.cue:373:16 } } @@ -1327,8 +1053,8 @@ #A: (#struct){ b: (int){ int } q: (#struct){ + d: (int){ int } c: (int){ int } - d: (int){ int } } } a: (_|_){ @@ -1337,21 +1063,17 @@ q: (_|_){ // [eval] c: (int){ 2 } - d: (int){ int } e: (_|_){ // [eval] a.q.e: field not allowed: - // ./in.cue:1:5 - // ./in.cue:6:5 // ./in.cue:7:3 - // ./in.cue:11:4 // ./in.cue:15:3 } + d: (int){ int } } } issue852: (_|_){ // [eval] issue852.a.Foo: field not allowed: - // ./in.cue:22:6 - // ./in.cue:26:5 + // ./in.cue:23:16 // ./in.cue:28:5 #A: (#struct){ } @@ -1359,8 +1081,7 @@ // [eval] Foo: (_|_){ // [eval] issue852.a.Foo: field not allowed: - // ./in.cue:22:6 - // ./in.cue:26:5 + // ./in.cue:23:16 // ./in.cue:28:5 } } @@ -1371,8 +1092,8 @@ foo: (int){ int } } d: (#struct){ - key: (string){ "foo" } foo: (int){ 3 } + key: (string){ "foo" } } } issue3330: (struct){ @@ -1386,13 +1107,7 @@ } } out: (#list){ - 0: (#struct){ - let empty#1 = (#struct){ - } - field: (#struct){ - n: (int){ 3 } - } - } + 0: ~(issue3330.let.ok.#struct) } } } @@ -1421,13 +1136,7 @@ g: (#struct){ } } - out: (#struct){ - field: (#struct){ - n: (int){ 3 } - } - g: (#struct){ - } - } + out: ~(issue3330.matthew.ok2.#struct) out2: (#struct){ field: (#struct){ n: (int){ 3 } @@ -1448,13 +1157,7 @@ d: (int){ 1 } } } - 0: (#struct){ - let b#2 = (#struct){ - } - c: (#struct){ - d: (int){ 1 } - } - } + 0: ~(issue3331.original.ok.#A) } } variant1: (struct){ @@ -1467,13 +1170,7 @@ } } 0: (#list){ - 0: (#struct){ - let b#3 = (#struct){ - } - c: (#struct){ - d: (int){ 1 } - } - } + 0: ~(issue3331.variant1.ok.#A) } } } @@ -1480,19 +1177,18 @@ } indirect: (_|_){ // [eval] - embed: (struct){ - err1: (struct){ - #A: (#struct){ - x: (#struct){ - a: (#struct){ - b: (int){ 1 } - c: (int){ 2 } - } - } - zx: (#struct){ - b: (int){ 1 } - c: (int){ 2 } - } + embed: (_|_){ + // [eval] + err1: (_|_){ + // [eval] + #A: (#struct){ + x: (#struct){ + a: (#struct){ + b: (int){ 1 } + c: (int){ 2 } + } + } + zx: ~(indirect.embed.err1.#A.x.a) } #x: (#struct){ a: (#struct){ @@ -1504,22 +1200,16 @@ c: (int){ 2 } } } - b: (#struct){ - x: (#struct){ - a: (#struct){ - b: (int){ 1 } - c: (int){ 2 } - } - } - zx: (#struct){ - b: (int){ 1 } - c: (int){ 2 } - } - } - b1: (struct){ + b: ~(indirect.embed.err1.#A) + b1: (_|_){ + // [eval] + d: (_|_){ + // [eval] indirect.embed.err1.b1.d: field not allowed: + // ./reroot.cue:67:7 + // ./reroot.cue:68:7 + } b: (int){ 1 } c: (int){ 2 } - d: (int){ 1 } } } } @@ -1536,22 +1226,17 @@ } Y: (_|_){ // [eval] + b: (#struct){ + } + c: (#struct){ + } a: (_|_){ // [eval] e: (_|_){ // [eval] indirect.closed.err1.Y.a.e: field not allowed: - // ./reroot.cue:73:7 - // ./reroot.cue:74:7 - // ./reroot.cue:75:7 - // ./reroot.cue:77:6 // ./reroot.cue:79:7 - // ./reroot.cue:80:7 - // ./reroot.cue:82:7 - } - } - b: (#struct){ - } - c: (#struct){ + // ./reroot.cue:75:7 + } } } #X: (#struct){ @@ -1571,25 +1256,11 @@ } } } - x: (#struct){ - b: (#struct){ - } - #B: (#struct){ - c: (#struct){ - d: (int){ 1 } - } - } - } - } - embed: (struct){ - ok: (struct){ - x: (#struct){ - d: (#struct){ - e: (int){ int } - } - b: (#struct){ - } - } + x: ~(nested.ok1.#A) + } + embed: (struct){ + ok: (struct){ + x: ~(nested.embed.ok.#A) #A: (#struct){ d: (#struct){ e: (int){ int } @@ -1614,69 +1285,29 @@ // [eval] f: (_|_){ // [eval] nested.err1.x.b.f: field not allowed: - // ./reroot.cue:112:5 - // ./reroot.cue:114:6 - // ./reroot.cue:122:8 - // ./reroot.cue:123:6 + // ./reroot.cue:114:6 } g: (_|_){ // [eval] nested.err1.x.b.g: field not allowed: - // ./reroot.cue:112:5 - // ./reroot.cue:114:6 - // ./reroot.cue:122:8 - // ./reroot.cue:123:6 - } - } - v: (_|_){ - // [eval] - c: (_|_){ - // [eval] - f: (_|_){ - // [eval] nested.err1.x.v.c.f: field not allowed: - // ./reroot.cue:112:5 - // ./reroot.cue:114:6 - // ./reroot.cue:115:6 - // ./reroot.cue:117:7 - // ./reroot.cue:117:11 - // ./reroot.cue:122:8 - // ./reroot.cue:123:6 - } - g: (int){ 1 } - d: (_|_){ - // [eval] nested.err1.x.v.c.d: field not allowed: - // ./reroot.cue:112:5 - // ./reroot.cue:114:6 - // ./reroot.cue:115:6 - // ./reroot.cue:117:7 - // ./reroot.cue:118:5 - // ./reroot.cue:122:8 - // ./reroot.cue:123:6 - } - } - } + // ./reroot.cue:122:8 + } + } + v: ~(nested.err1.x.#V) #V: (_|_){ // [eval] c: (_|_){ // [eval] - f: (_|_){ - // [eval] nested.err1.x.#V.c.f: field not allowed: - // ./reroot.cue:112:5 - // ./reroot.cue:114:6 - // ./reroot.cue:117:7 - // ./reroot.cue:117:11 - // ./reroot.cue:122:8 - // ./reroot.cue:123:6 - } - g: (int){ 1 } d: (_|_){ // [eval] nested.err1.x.#V.c.d: field not allowed: - // ./reroot.cue:112:5 - // ./reroot.cue:114:6 - // ./reroot.cue:117:7 - // ./reroot.cue:118:5 - // ./reroot.cue:122:8 - // ./reroot.cue:123:6 - } + // ./reroot.cue:122:8 + // ./reroot.cue:118:5 + } + f: (_|_){ + // [eval] nested.err1.x.#V.c.f: field not allowed: + // ./reroot.cue:122:8 + // ./reroot.cue:114:6 + } + g: (int){ 1 } } } } @@ -1684,16 +1315,11 @@ b: (#struct){ f: (int){ 1 } } - v: (#struct){ - c: (#struct){ - f: (int){ 1 } - d: (int){ 1 } - } - } + v: ~(nested.err1.#A.#V) #V: (#struct){ c: (#struct){ - f: (int){ 1 } - d: (int){ 1 } + d: (int){ 1 } + f: (int){ 1 } } } } @@ -1716,19 +1342,18 @@ // [eval] g: (_|_){ // [eval] nested.err2.x.b.g: field not allowed: - // ./reroot.cue:128:6 - // ./reroot.cue:136:5 // ./reroot.cue:137:8 } } c: (#struct){ + d: (int){ 1 } g: (int){ 1 } - d: (int){ 1 } - } - } - } - } - inline: (struct){ + } + } + } + } + inline: (_|_){ + // [eval] #x: (#struct){ y: (#struct){ z?: (#struct){ @@ -1736,81 +1361,112 @@ } } } - err1: (struct){ - name: (string){ "a" } - age1: (int){ 5 } - } - err2: (struct){ - name: (string){ "a" } - age2: (int){ 5 } - } - } - mixInDef: (struct){ - refInside: (struct){ - #x: (#struct){ - b: (#struct){ - c: (#struct){ - d: (#struct){ - } - e: (#struct){ - f: (#struct){ - } - } - } - } - } - a: (#struct){ - b: (#struct){ - c: (#struct){ - d: (#struct){ - } - e: (#struct){ - f: (#struct){ - } - } - } - } - } - } - refEdge: (struct){ - #x: (#struct){ - c: (#struct){ - d: (#struct){ - } - e: (#struct){ - f: (#struct){ - } - } - } - } - a: (#struct){ - c: (#struct){ - d: (#struct){ - } - e: (#struct){ - f: (#struct){ - } - } - } - } - } - refOutside: (struct){ - #x: (#struct){ - c: (#struct){ - d: (#struct){ - } - e: (#struct){ - f: (#struct){ - } - } - } - } - a: (#struct){ - c: (#struct){ - d: (#struct){ - } - e: (#struct){ - f: (#struct){ + err1: (_|_){ + // [eval] + name: (string){ "a" } + age1: (_|_){ + // [eval] inline.err1.age1: field not allowed: + // ./reroot.cue:145:3 + } + } + err2: (_|_){ + // [eval] + name: (string){ "a" } + age2: (_|_){ + // [eval] inline.err2.age2: field not allowed: + // ./reroot.cue:149:3 + } + } + } + mixInDef: (_|_){ + // [eval] + refInside: (_|_){ + // [eval] + #x: (#struct){ + b: (#struct){ + c: (#struct){ + d: (#struct){ + } + e: (#struct){ + f: (#struct){ + } + } + } + } + } + a: (_|_){ + // [eval] + b: (_|_){ + // [eval] + c: (_|_){ + // [eval] + d: (#struct){ + } + e: (_|_){ + // [eval] + f: (_|_){ + // [eval] mixInDef.refInside.a.b.c.e.f: field not allowed: + // ./reroot.cue:160:15 + // ./reroot.cue:157:24 + } + } + } + } + } + } + refEdge: (_|_){ + // [eval] + #x: (#struct){ + c: (#struct){ + d: (#struct){ + } + e: (#struct){ + f: (#struct){ + } + } + } + } + a: (_|_){ + // [eval] + c: (_|_){ + // [eval] + d: (#struct){ + } + e: (_|_){ + // [eval] + f: (_|_){ + // [eval] mixInDef.refEdge.a.c.e.f: field not allowed: + // ./reroot.cue:166:12 + // ./reroot.cue:163:21 + } + } + } + } + } + refOutside: (_|_){ + // [eval] + #x: (#struct){ + c: (#struct){ + d: (#struct){ + } + e: (#struct){ + f: (#struct){ + } + } + } + } + a: (_|_){ + // [eval] + c: (_|_){ + // [eval] + d: (#struct){ + } + e: (_|_){ + // [eval] + f: (_|_){ + // [eval] mixInDef.refOutside.a.c.e.f: field not allowed: + // ./reroot.cue:172:12 + // ./reroot.cue:169:21 } } } @@ -1887,8 +1543,8 @@ } } original: (struct){ - Y: (struct){ - b: (struct){ + Y: (#struct){ + b: (#struct){ c: (string){ "v1" } } } @@ -1899,8 +1555,8 @@ } } moreInlining: (struct){ - out: (struct){ - b: (struct){ + out: (#struct){ + b: (#struct){ c: (string){ "v1" } } } @@ -1924,8 +1580,8 @@ empty: (#struct){ } } - out: (struct){ - b: (struct){ + out: (#struct){ + b: (#struct){ c: (string){ "v1" } } } @@ -1942,8 +1598,8 @@ empty: (#struct){ } } - Y: (struct){ - c: (struct){ + Y: (#struct){ + c: (#struct){ d: (string){ "v1" } } } -- diff/todo/p2 -- Positions / reordering -- diff/explanation -- inline.err*.age*: fields are now correctly not allowed. patterns.*.andOrEmbed.t2.ok2: erroneous in V2 mixInDef: arguably should all be erroneous, but definitely refOutside. indirect.embed: now correctly fails for V3. -- out/compile -- --- embed.cue { issue3325: { ok: { #Items: { [string]: { name: 〈1;-〉 } } #Base: { name: "base" type: string items: 〈1;#Items〉 } #Extended: (〈0;#Base〉 & { type: "extended" items: { "my-item": {} } }) broken: { 〈1;#Base〉 〈1;#Extended〉 } works: { 〈1;#Extended〉 〈1;#Base〉 } } } patterns: { shallow: { #a: { [>="k"]: int } #b: { [<="m"]: int } #c: { [>="w"]: int } #d: { [<="y"]: int } single: { X: 〈1;#a〉 err: 〈0;X〉 err: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } and: { p1: { X: (〈2;#a〉 & 〈2;#b〉) err: 〈0;X〉 err: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } } and: { p2: { X: (〈2;#b〉 & 〈2;#a〉) err: 〈0;X〉 err: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } } andEmbed: { p1: { X: { (〈3;#a〉 & 〈3;#b〉) } err: 〈0;X〉 err: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } } andEmbed: { p2: { X: { (〈3;#b〉 & 〈3;#a〉) } err: 〈0;X〉 err: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } } orEmbed: { p1: { X: { 〈3;#a〉 〈3;#b〉 } ok1: 〈0;X〉 ok1: { j: 3 } ok2: 〈0;X〉 ok2: { k: 3 } } } orEmbed: { p2: { X: { 〈3;#b〉 〈3;#a〉 } ok1: 〈0;X〉 ok1: { j: 3 } ok2: 〈0;X〉 ok2: { k: 3 } } } andOrEmbed: { t1: { p1: { X: { (〈4;#a〉 & 〈4;#b〉) (〈4;#c〉 & 〈4;#d〉) } err1: 〈0;X〉 err1: { j: 3 } ok1: 〈0;X〉 ok1: { k: 3 } } } } andOrEmbed: { t1: { p2: { X: { (〈4;#c〉 & 〈4;#d〉) (〈4;#a〉 & 〈4;#b〉) } err1: 〈0;X〉 err1: { j: 3 } ok1: 〈0;X〉 ok1: { k: 3 } } } } andOrEmbed: { t2: { X: { (〈3;#a〉 & 〈3;#b〉) (〈3;#c〉 & 〈3;#d〉) ["p"]: int } err1: 〈0;X〉 err1: { j: 3 } ok1: 〈0;X〉 ok1: { k: 3 } ok2: 〈0;X〉 ok2: { p: 3 } } } indirect: { a: { [>="k"]: int } #a: 〈0;a〉 p1: { X: 〈1;#a〉 err1: 〈0;X〉 err1: { j: 3 } err2: (〈0;X〉 & _|_(no sharing)) err2: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } p2: { #a: (〈1;a〉 & _|_(no sharing)) X: 〈0;#a〉 err1: 〈0;X〉 err1: { j: 3 } err2: (〈0;X〉 & _|_(no sharing)) err2: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } p3: { X: (〈1;#a〉 & _|_(no sharing)) err1: 〈0;X〉 err1: { j: 3 } err2: (〈0;X〉 & _|_(no sharing)) err2: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } p4: { #a: (〈1;a〉 & _|_(no sharing)) X: 〈0;#a〉 X: (〈0;#a〉 & _|_(no sharing)) err1: 〈0;X〉 err1: { j: 3 } err2: (〈0;X〉 & _|_(no sharing)) err2: { j: 3 } ok: 〈0;X〉 ok: { k: 3 } } } } } patterns: { nested: { #a: { x: { y: { [>="k"]: int } } } #b: { x: { y: { [<="m"]: int } } } #c: { x: { y: { [>="w"]: int } } } #d: { x: { y: { [<="y"]: int } } } single: { X: 〈1;#a〉 err: 〈0;X〉 err: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } and: { p1: { X: (〈2;#a〉 & 〈2;#b〉) err: 〈0;X〉 err: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } } and: { p2: { X: (〈2;#b〉 & 〈2;#a〉) err: 〈0;X〉 err: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } } andEmbed: { p1: { X: { (〈3;#a〉 & 〈3;#b〉) } err: 〈0;X〉 err: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } } andEmbed: { p2: { X: { (〈3;#b〉 & 〈3;#a〉) } err: 〈0;X〉 err: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } } orEmbed: { p1: { X: { 〈3;#a〉 〈3;#b〉 } ok1: 〈0;X〉 ok1: { x: { y: { j: 3 } } } ok2: 〈0;X〉 ok2: { x: { y: { k: 3 } } } } } orEmbed: { p2: { X: { 〈3;#b〉 〈3;#a〉 } ok1: 〈0;X〉 ok1: { x: { y: { j: 3 } } } ok2: 〈0;X〉 ok2: { x: { y: { k: 3 } } } } } andOrEmbed: { t1: { p1: { X: { (〈4;#a〉 & 〈4;#b〉) (〈4;#c〉 & 〈4;#d〉) } err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } ok1: 〈0;X〉 ok1: { x: { y: { k: 3 } } } } } } andOrEmbed: { t1: { p2: { X: { (〈4;#c〉 & 〈4;#d〉) (〈4;#a〉 & 〈4;#b〉) } err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } ok1: 〈0;X〉 ok1: { x: { y: { k: 3 } } } } } } andOrEmbed: { t2: { X: { (〈3;#a〉 & 〈3;#b〉) (〈3;#c〉 & 〈3;#d〉) ["p"]: int } err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } ok1: 〈0;X〉 ok1: { x: { y: { k: 3 } } } ok2: 〈0;X〉 ok2: { x: { y: { p: 3 } } } } } indirect: { a: { x: { y: { [>="k"]: int } } } #a: 〈0;a〉 p1: { X: 〈1;#a〉 err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } err2: (〈0;X〉 & _|_(no sharing)) err2: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } p2: { #a: (〈1;a〉 & _|_(no sharing)) X: 〈0;#a〉 err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } err2: (〈0;X〉 & _|_(no sharing)) err2: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } p3: { X: (〈1;#a〉 & _|_(no sharing)) err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } err2: (〈0;X〉 & _|_(no sharing)) err2: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } p4: { #a: (〈1;a〉 & _|_(no sharing)) X: 〈0;#a〉 X: (〈0;#a〉 & _|_(no sharing)) err1: 〈0;X〉 err1: { x: { y: { j: 3 } } } err2: (〈0;X〉 & _|_(no sharing)) err2: { x: { y: { j: 3 } } } ok: 〈0;X〉 ok: { x: { y: { k: 3 } } } } } } } } --- in.cue { #E: { c: int } #A: { b: int q: { 〈2;#E〉 d: int } } a: (〈0;#A〉 & { b: 3 q: { c: 2 e: 43 } }) issue852: { #A: { [=~"^a-z$"]: string } a: 〈0;#A〉 a: { Foo: "foo" } for k, v in 〈0;a〉 { b: { "\(〈2;k〉)": 〈2;v〉 } } } dynamic: { #D: { key: "foo" 〈0;key〉: int } d: (〈0;#D〉 & { foo: 3 }) } } --- reroot.cue { issue3330: { let: { ok: { #struct: { let empty#1 = {} field: (null|{ n: int }) field: (〈0;let empty#1〉 & { n: 3 }) } out: 〈import;list〉.Concat([ [ 〈2;#struct〉, ], ]) } } matthew: { ok1: { #struct: { field: ({ n: 3 } & 〈0;g〉) g: {} } out: (〈0;#struct〉 & {}) } } matthew: { ok2: { #struct: { field: ({ n: 3 } & 〈0;g〉) g: {} } out: 〈0;#struct〉 out2: (〈0;out〉 & {}) } } } issue3331: { original: { ok: { #A: { let b#2 = {} c: (〈0;let b#2〉 & { d: 1 }) } 〈import;list〉.Concat([ [ 〈2;#A〉, ], ]) } } variant1: { ok: { #A: { let b#3 = {} c: (〈0;let b#3〉 & { d: 1 }) } [ [ 〈2;#A〉, ], ] } } } indirect: { embed: { err1: { #A: { x: { 〈2;#x〉 〈2;#y〉 } zx: 〈0;x〉.a } #x: { a: { b: 1 } } #y: { a: { c: 2 } } b: 〈0;#A〉 b1: 〈0;b〉.zx b1: { d: 1 } } } closed: { err1: { X: { a: 〈0;b〉 b: {} a: { e: 1 } } Y: 〈0;X〉 Y: { b: 〈0;c〉 c: 〈1;#X〉 } #X: {} } } } nested: { ok1: { #A: { b: {} #B: { c: (〈1;b〉 & { d: 1 }) } } x: 〈0;#A〉 } } nested: { embed: { ok: { x: 〈0;#A〉 #A: { 〈1;k〉 } k: { d: (〈0;b〉 & { e: int }) b: {} } } } } nested: { err1: { x: 〈0;#A〉 #A: { b: { f: 1 } v: 〈0;#V〉 #V: { c: (〈1;b〉 & { d: 1 }) } } x: { b: 〈1;#B〉 } #B: { g: 1 } } } nested: { err2: { #A: { b: {} c: (〈0;b〉 & { d: 1 }) } x: 〈0;#A〉 x: { b: { g: 1 } } } } inline: { #x: { y: { z?: { name: string } } } err1: ((〈0;#x〉 & { y: { z: _ } }).y.z & { name: "a" age1: 5 }) err2: ((〈0;#x〉.y & { z: _ }).z & { name: "a" age2: 5 }) } mixInDef: { refInside: { #x: { b: { c: { d: {} e: { f: {} } } } } a: 〈0;#x〉 a: { b: { c: { d: {} } } } a: { b: { c: { e: 〈1;c〉.d } } } } refEdge: { #x: { c: { d: {} e: { f: {} } } } a: 〈0;#x〉 a: { c: { d: {} } } a: { c: { e: 〈1;c〉.d } } } refOutside: { #x: { c: { d: {} e: { f: {} } } } a: 〈0;#x〉 a: { c: { d: {} } } a: { c: { e: 〈2;a〉.c.d } } } } issue3601: { original: { out: { 〈1;#Transform〉.output } #Transform: { output: (〈1;#Patch〉 & {}).output } #Patch: { target: {} output: { foo: { final: 〈2;target〉 final: { version: "v1" } } } } } } issue3601: { originalNoShare: { out: { 〈1;#Transform〉.output } #Transform: { output: (〈1;#Patch〉 & _|_(no sharing)).output } #Patch: { target: {} output: { foo: { final: 〈2;target〉 final: { version: "v1" } } } } } } issue3601: { reduced: { #X: { a: { b: { c: "v1" } } a: { b: 〈1;empty〉 } empty: {} } original: { Y: (〈1;#X〉 & _|_(no sharing)).a out: (〈0;Y〉 & _|_(no sharing)) } moreInlining: { out: ((〈1;#X〉 & {}).a & {}) } noInline: { Y: (〈1;#X〉 & _|_(no sharing)) Z: (〈0;Y〉 & _|_(no sharing)) out: (〈0;Z〉.a & _|_(no sharing)) } moreNesting: { #X: { a: { b: { c: { d: "v1" } } } a: { b: { c: 〈2;empty〉 } } empty: {} } Y: (〈0;#X〉.a & _|_(no sharing)).b Z: (〈0;Y〉 & _|_(no sharing)) } } } } --- validation.cue { issue3332: { #def: { field: 〈import;list〉.MinItems(1) } use: (〈0;#def〉 & { field: [ "value", ] }) } } cue-lang-cue-db9cc73/cue/testdata/eval/comprehensions.txtar000066400000000000000000000271401474664451600241400ustar00rootroot00000000000000-- in.cue -- import "strings" a: {x: 10, y: 100, z: 50} b: { for k, v in a if v <= 50 { "\(k)": v } x: int if x > 3 { k: 20 } k: int if k > 0 { l: 40 } } c: { for k, v in a let y = v + 10 if y > 50 { "\(k)": y } } A: X: run: "dfoo" if true { A: X: { run: string files: "\(strings.Join([ run], "\n"))" } } matchOrder: { a1: { out: [string]: Val: 1 out: in.a in: a: { if true { b: {} } } } a2: { out: [string]: Val: 1 in: a: { if true { b: {} } } out: in.a } a3: { in: a: { if true { b: {} } } out: [string]: Val: 1 out: in.a } a4: { out: in.a out: [string]: Val: 1 in: a: { if true { b: {} } } } a5: { out: in.a in: a: { if true { b: {} } } out: [string]: Val: 1 } a6: { in: a: { if true { b: {} } } out: in.a out: [string]: Val: 1 } } -- issue3691.cue -- // Ensure that parent nodes are properly processed, even when a pending arc // is evaluated early. issue3691: original: { X: [string]: string a: [string]: X a: { if true { b: c: 1 } } } // Structural cycles follow a different code path. issue3691: structuralCycle: { X: [string]: string a: [string]: X a: { if true { b: c: a } } } -- out/eval/stats -- Leaks: 4 Freed: 77 Reused: 69 Allocs: 12 Retain: 19 Unifications: 81 Conjuncts: 121 Disjuncts: 94 -- out/evalalpha -- Errors: issue3691.original.a.b: conflicting values 1 and string (mismatched types int and string): ./issue3691.cue:4:15 ./issue3691.cue:8:10 issue3691.structuralCycle.a.b.c: structural cycle Result: (_|_){ // [eval] a: (struct){ x: (int){ 10 } y: (int){ 100 } z: (int){ 50 } } b: (struct){ x: (int){ 10 } k: (int){ 20 } l: (int){ 40 } z: (int){ 50 } } c: (struct){ y: (int){ 110 } z: (int){ 60 } } A: (struct){ X: (struct){ run: (string){ "dfoo" } files: (string){ "dfoo" } } } matchOrder: (struct){ a1: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a2: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a3: (struct){ in: (struct){ a: (struct){ b: (struct){ } } } out: (struct){ b: (struct){ Val: (int){ 1 } } } } a4: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a5: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a6: (struct){ in: (struct){ a: (struct){ b: (struct){ } } } out: (struct){ b: (struct){ Val: (int){ 1 } } } } } issue3691: (_|_){ // [eval] original: (_|_){ // [eval] X: (struct){ } a: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] issue3691.original.a.b: conflicting values 1 and string (mismatched types int and string): // ./issue3691.cue:4:15 // ./issue3691.cue:8:10 } } } } structuralCycle: (_|_){ // [structural cycle] X: (struct){ } a: (_|_){ // [structural cycle] b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] issue3691.structuralCycle.a.b.c: structural cycle } } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,14 +1,8 @@ Errors: -issue3691.original.a.b.c: conflicting values string and 1 (mismatched types string and int): +issue3691.original.a.b: conflicting values 1 and string (mismatched types int and string): ./issue3691.cue:4:15 - ./issue3691.cue:7:3 ./issue3691.cue:8:10 -issue3691.structuralCycle.a.b.c: conflicting values string and {[string]:X} (mismatched types string and struct): - ./issue3691.cue:14:15 - ./issue3691.cue:15:5 - ./issue3691.cue:17:3 - ./issue3691.cue:18:10 -issue3691.structuralCycle.a.b.c.b.c: structural cycle +issue3691.structuralCycle.a.b.c: structural cycle Result: (_|_){ @@ -125,9 +119,8 @@ b: (_|_){ // [eval] c: (_|_){ - // [eval] issue3691.original.a.b.c: conflicting values string and 1 (mismatched types string and int): + // [eval] issue3691.original.a.b: conflicting values 1 and string (mismatched types int and string): // ./issue3691.cue:4:15 - // ./issue3691.cue:7:3 // ./issue3691.cue:8:10 } } @@ -134,25 +127,15 @@ } } structuralCycle: (_|_){ - // [eval] - X: (struct){ - } - a: (_|_){ - // [eval] - b: (_|_){ - // [eval] - c: (_|_){ - // [eval] issue3691.structuralCycle.a.b.c: conflicting values string and {[string]:X} (mismatched types string and struct): - // ./issue3691.cue:14:15 - // ./issue3691.cue:15:5 - // ./issue3691.cue:17:3 - // ./issue3691.cue:18:10 - b: (_|_){ - // [structural cycle] - c: (_|_){ - // [structural cycle] issue3691.structuralCycle.a.b.c.b.c: structural cycle - } - } + // [structural cycle] + X: (struct){ + } + a: (_|_){ + // [structural cycle] + b: (_|_){ + // [structural cycle] + c: (_|_){ + // [structural cycle] issue3691.structuralCycle.a.b.c: structural cycle } } } -- diff/todo/p2 -- Missing error positions. -- out/eval -- Errors: issue3691.original.a.b.c: conflicting values string and 1 (mismatched types string and int): ./issue3691.cue:4:15 ./issue3691.cue:7:3 ./issue3691.cue:8:10 issue3691.structuralCycle.a.b.c: conflicting values string and {[string]:X} (mismatched types string and struct): ./issue3691.cue:14:15 ./issue3691.cue:15:5 ./issue3691.cue:17:3 ./issue3691.cue:18:10 issue3691.structuralCycle.a.b.c.b.c: structural cycle Result: (_|_){ // [eval] a: (struct){ x: (int){ 10 } y: (int){ 100 } z: (int){ 50 } } b: (struct){ x: (int){ 10 } k: (int){ 20 } l: (int){ 40 } z: (int){ 50 } } c: (struct){ y: (int){ 110 } z: (int){ 60 } } A: (struct){ X: (struct){ run: (string){ "dfoo" } files: (string){ "dfoo" } } } matchOrder: (struct){ a1: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a2: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a3: (struct){ in: (struct){ a: (struct){ b: (struct){ } } } out: (struct){ b: (struct){ Val: (int){ 1 } } } } a4: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a5: (struct){ out: (struct){ b: (struct){ Val: (int){ 1 } } } in: (struct){ a: (struct){ b: (struct){ } } } } a6: (struct){ in: (struct){ a: (struct){ b: (struct){ } } } out: (struct){ b: (struct){ Val: (int){ 1 } } } } } issue3691: (_|_){ // [eval] original: (_|_){ // [eval] X: (struct){ } a: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] issue3691.original.a.b.c: conflicting values string and 1 (mismatched types string and int): // ./issue3691.cue:4:15 // ./issue3691.cue:7:3 // ./issue3691.cue:8:10 } } } } structuralCycle: (_|_){ // [eval] X: (struct){ } a: (_|_){ // [eval] b: (_|_){ // [eval] c: (_|_){ // [eval] issue3691.structuralCycle.a.b.c: conflicting values string and {[string]:X} (mismatched types string and struct): // ./issue3691.cue:14:15 // ./issue3691.cue:15:5 // ./issue3691.cue:17:3 // ./issue3691.cue:18:10 b: (_|_){ // [structural cycle] c: (_|_){ // [structural cycle] issue3691.structuralCycle.a.b.c.b.c: structural cycle } } } } } } } } -- out/compile -- --- in.cue { a: { x: 10 y: 100 z: 50 } b: { for k, v in 〈1;a〉 if (〈0;v〉 <= 50) { "\(〈1;k〉)": 〈1;v〉 } x: int if (〈0;x〉 > 3) { k: 20 } k: int if (〈0;k〉 > 0) { l: 40 } } c: { for k, v in 〈1;a〉 let y = (〈0;v〉 + 10) if (〈0;y〉 > 50) { "\(〈2;k〉)": 〈1;y〉 } } A: { X: { run: "dfoo" } } if true { A: { X: { run: string files: "\(〈import;strings〉.Join([ 〈1;run〉, ], "\n"))" } } } matchOrder: { a1: { out: { [string]: { Val: 1 } } out: 〈0;in〉.a in: { a: { if true { b: {} } } } } a2: { out: { [string]: { Val: 1 } } in: { a: { if true { b: {} } } } out: 〈0;in〉.a } a3: { in: { a: { if true { b: {} } } } out: { [string]: { Val: 1 } } out: 〈0;in〉.a } a4: { out: 〈0;in〉.a out: { [string]: { Val: 1 } } in: { a: { if true { b: {} } } } } a5: { out: 〈0;in〉.a in: { a: { if true { b: {} } } } out: { [string]: { Val: 1 } } } a6: { in: { a: { if true { b: {} } } } out: 〈0;in〉.a out: { [string]: { Val: 1 } } } } } --- issue3691.cue { issue3691: { original: { X: { [string]: string } a: { [string]: 〈1;X〉 } a: { if true { b: { c: 1 } } } } } issue3691: { structuralCycle: { X: { [string]: string } a: { [string]: 〈1;X〉 } a: { if true { b: { c: 〈3;a〉 } } } } } } cue-lang-cue-db9cc73/cue/testdata/eval/conflicts.txtar000066400000000000000000000062271474664451600230730ustar00rootroot00000000000000-- in.cue -- i: int s: string t0: { v: i & s } t1: { #d1: { a: b: 3 } #d2: { a: b: 4 } x: #d1 & #d2 } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 10 Allocs: 5 Retain: 0 Unifications: 15 Conjuncts: 23 Disjuncts: 15 -- out/evalalpha -- Errors: t0.v: conflicting values int and string (mismatched types int and string): ./in.cue:1:4 ./in.cue:2:4 t1.x.a.b: conflicting values 4 and 3: ./in.cue:10:9 ./in.cue:14:9 Result: (_|_){ // [eval] i: (int){ int } s: (string){ string } t0: (_|_){ // [eval] v: (_|_){ // [eval] t0.v: conflicting values int and string (mismatched types int and string): // ./in.cue:1:4 // ./in.cue:2:4 } } t1: (_|_){ // [eval] #d1: (#struct){ a: (#struct){ b: (int){ 3 } } } #d2: (#struct){ a: (#struct){ b: (int){ 4 } } } x: (_|_){ // [eval] a: (_|_){ // [eval] b: (_|_){ // [eval] t1.x.a.b: conflicting values 4 and 3: // ./in.cue:10:9 // ./in.cue:14:9 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,12 +2,9 @@ t0.v: conflicting values int and string (mismatched types int and string): ./in.cue:1:4 ./in.cue:2:4 - ./in.cue:5:9 t1.x.a.b: conflicting values 4 and 3: ./in.cue:10:9 ./in.cue:14:9 - ./in.cue:17:5 - ./in.cue:17:11 Result: (_|_){ @@ -20,7 +17,6 @@ // [eval] t0.v: conflicting values int and string (mismatched types int and string): // ./in.cue:1:4 // ./in.cue:2:4 - // ./in.cue:5:9 } } t1: (_|_){ @@ -43,8 +39,6 @@ // [eval] t1.x.a.b: conflicting values 4 and 3: // ./in.cue:10:9 // ./in.cue:14:9 - // ./in.cue:17:5 - // ./in.cue:17:11 } } } -- diff/todo/p2 -- Positions. -- out/eval -- Errors: t0.v: conflicting values int and string (mismatched types int and string): ./in.cue:1:4 ./in.cue:2:4 ./in.cue:5:9 t1.x.a.b: conflicting values 4 and 3: ./in.cue:10:9 ./in.cue:14:9 ./in.cue:17:5 ./in.cue:17:11 Result: (_|_){ // [eval] i: (int){ int } s: (string){ string } t0: (_|_){ // [eval] v: (_|_){ // [eval] t0.v: conflicting values int and string (mismatched types int and string): // ./in.cue:1:4 // ./in.cue:2:4 // ./in.cue:5:9 } } t1: (_|_){ // [eval] #d1: (#struct){ a: (#struct){ b: (int){ 3 } } } #d2: (#struct){ a: (#struct){ b: (int){ 4 } } } x: (_|_){ // [eval] a: (_|_){ // [eval] b: (_|_){ // [eval] t1.x.a.b: conflicting values 4 and 3: // ./in.cue:10:9 // ./in.cue:14:9 // ./in.cue:17:5 // ./in.cue:17:11 } } } } } -- out/compile -- --- in.cue { i: int s: string t0: { v: (〈1;i〉 & 〈1;s〉) } t1: { #d1: { a: { b: 3 } } #d2: { a: { b: 4 } } x: (〈0;#d1〉 & 〈0;#d2〉) } } cue-lang-cue-db9cc73/cue/testdata/eval/conjuncts.txtar000066400000000000000000000207311474664451600231110ustar00rootroot00000000000000// These tests are related to issue 2351. -- in.cue -- conjunct: t1: { #early: *"X" | string #early } & { #early: *"X" | string string } conjunct: t2: { #early: *"X" | string #early } conjunct: t2: { #early: *"X" | string string } // TODO: fix this test conjunct: t3: conjunct.t1 & conjunct.t2 handleComprehensions: { if false { subs: #sub2 & 2 } #sub2: 2 } -- issue2351.cue -- issue2351: let: { let _param = "foo" ({ param: _param & [{}] gen: [for p in param {p}] }).gen } issue2351: hidden: { _in1: ["foo"] { in2: _in1 out: [for x in in2 {x}] }.out } -- issue2355.cue -- issue2355: { #GetF1: { in: _ out: in.f1 } #PutOut1: { in: _ out: out1: "\(in)" } export: { let data = {f1: "foo"} (#PutOut1 & { in: (#GetF1 & { in: data }).out }).out } } -- out/evalalpha/stats -- Leaks: 246 Freed: 0 Reused: 0 Allocs: 246 Retain: 0 Unifications: 43 Conjuncts: 426 Disjuncts: 152 -- out/evalalpha -- Errors: param: conflicting values [{}] and "foo" (mismatched types list and string): ./issue2351.cue:2:15 ./issue2351.cue:4:19 Result: (_|_){ // [eval] conjunct: (struct){ t1: (string){ |(*(string){ "X" #early: (string){ |(*(string){ "X" }, (string){ string }) } }, (string){ string #early: (string){ |(*(string){ "X" }, (string){ string }) } }) } t2: (string){ |(*(string){ "X" #early: (string){ |(*(string){ "X" }, (string){ string }) } }, (string){ string #early: (string){ |(*(string){ "X" }, (string){ string }) } }) } t3: (string){ |(*(string){ "X" #early: (string){ |(*(string){ "X" }, (string){ string }) } }, (string){ string #early: (string){ |(*(string){ "X" }, (string){ string }) } }) } } handleComprehensions: (struct){ #sub2: (int){ 2 } } issue2351: (_|_){ // [eval] let: (_|_){ // [eval] param: conflicting values [{}] and "foo" (mismatched types list and string): // ./issue2351.cue:2:15 // ./issue2351.cue:4:19 let _param#1 = (string){ "foo" } } hidden: (#list){ _in1: (#list){ 0: (string){ "foo" } } 0: (string){ "foo" } } } issue2355: (struct){ #GetF1: (#struct){ in: (_){ _ } out: (_|_){ // [incomplete] issue2355.#GetF1.out: in.f1 undefined as in is incomplete (type _): // ./issue2355.cue:4:8 } } #PutOut1: (#struct){ in: (_){ _ } out: (#struct){ out1: (_|_){ // [incomplete] issue2355.#PutOut1.out.out1: invalid interpolation: non-concrete value _ (type _): // ./issue2355.cue:9:14 } } } export: (#struct){ let data#2 = (struct){ f1: (string){ "foo" } } out1: (string){ "foo" } } } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 9 -Freed: 68 -Reused: 59 -Allocs: 18 -Retain: 22 +Leaks: 246 +Freed: 0 +Reused: 0 +Allocs: 246 +Retain: 0 -Unifications: 45 -Conjuncts: 135 -Disjuncts: 86 +Unifications: 43 +Conjuncts: 426 +Disjuncts: 152 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,7 +1,6 @@ Errors: -issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list): +param: conflicting values [{}] and "foo" (mismatched types list and string): ./issue2351.cue:2:15 - ./issue2351.cue:3:2 ./issue2351.cue:4:19 Result: @@ -22,14 +21,13 @@ string #early: (string){ |(*(string){ "X" }, (string){ string }) } }) } - t3: (_|_){ - // [incomplete] conjunct.t3: 2 errors in empty disjunction: - // conjunct.t3: cannot add field #early: was already used: - // ./in.cue:6:2 - // conjunct.t3: cannot add field #early: was already used: - // ./in.cue:15:2 - #early: (string){ |(*(string){ "X" }, (string){ string }) } - } + t3: (string){ |(*(string){ + "X" + #early: (string){ |(*(string){ "X" }, (string){ string }) } + }, (string){ + string + #early: (string){ |(*(string){ "X" }, (string){ string }) } + }) } } handleComprehensions: (struct){ #sub2: (int){ 2 } @@ -37,9 +35,8 @@ issue2351: (_|_){ // [eval] let: (_|_){ - // [eval] issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list): + // [eval] param: conflicting values [{}] and "foo" (mismatched types list and string): // ./issue2351.cue:2:15 - // ./issue2351.cue:3:2 // ./issue2351.cue:4:19 let _param#1 = (string){ "foo" } } @@ -67,7 +64,7 @@ } } } - export: (struct){ + export: (#struct){ let data#2 = (struct){ f1: (string){ "foo" } } -- out/eval/stats -- Leaks: 9 Freed: 68 Reused: 59 Allocs: 18 Retain: 22 Unifications: 45 Conjuncts: 135 Disjuncts: 86 -- diff/todo/p3 -- Missing error position. -- diff/explanation -- conjunct.t3: this used to be broken, but is now fixed. issue2355.export: correctly closing in new evaluator. -- out/eval -- Errors: issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list): ./issue2351.cue:2:15 ./issue2351.cue:3:2 ./issue2351.cue:4:19 Result: (_|_){ // [eval] conjunct: (struct){ t1: (string){ |(*(string){ "X" #early: (string){ |(*(string){ "X" }, (string){ string }) } }, (string){ string #early: (string){ |(*(string){ "X" }, (string){ string }) } }) } t2: (string){ |(*(string){ "X" #early: (string){ |(*(string){ "X" }, (string){ string }) } }, (string){ string #early: (string){ |(*(string){ "X" }, (string){ string }) } }) } t3: (_|_){ // [incomplete] conjunct.t3: 2 errors in empty disjunction: // conjunct.t3: cannot add field #early: was already used: // ./in.cue:6:2 // conjunct.t3: cannot add field #early: was already used: // ./in.cue:15:2 #early: (string){ |(*(string){ "X" }, (string){ string }) } } } handleComprehensions: (struct){ #sub2: (int){ 2 } } issue2351: (_|_){ // [eval] let: (_|_){ // [eval] issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list): // ./issue2351.cue:2:15 // ./issue2351.cue:3:2 // ./issue2351.cue:4:19 let _param#1 = (string){ "foo" } } hidden: (#list){ _in1: (#list){ 0: (string){ "foo" } } 0: (string){ "foo" } } } issue2355: (struct){ #GetF1: (#struct){ in: (_){ _ } out: (_|_){ // [incomplete] issue2355.#GetF1.out: in.f1 undefined as in is incomplete (type _): // ./issue2355.cue:4:8 } } #PutOut1: (#struct){ in: (_){ _ } out: (#struct){ out1: (_|_){ // [incomplete] issue2355.#PutOut1.out.out1: invalid interpolation: non-concrete value _ (type _): // ./issue2355.cue:9:14 } } } export: (struct){ let data#2 = (struct){ f1: (string){ "foo" } } out1: (string){ "foo" } } } } -- out/compile -- --- in.cue { conjunct: { t1: ({ #early: (*"X"|string) 〈0;#early〉 } & { #early: (*"X"|string) string }) } conjunct: { t2: { #early: (*"X"|string) 〈0;#early〉 } } conjunct: { t2: { #early: (*"X"|string) string } } conjunct: { t3: (〈1;conjunct〉.t1 & 〈1;conjunct〉.t2) } handleComprehensions: { if false { subs: (〈1;#sub2〉 & 2) } #sub2: 2 } } --- issue2351.cue { issue2351: { let: { let _param#1 = "foo" { param: (〈1;let _param#1〉 & [ {}, ]) gen: [ for _, p in 〈1;param〉 { 〈1;p〉 }, ] }.gen } } issue2351: { hidden: { _in1: [ "foo", ] { in2: 〈1;_in1〉 out: [ for _, x in 〈1;in2〉 { 〈1;x〉 }, ] }.out } } } --- issue2355.cue { issue2355: { #GetF1: { in: _ out: 〈0;in〉.f1 } #PutOut1: { in: _ out: { out1: "\(〈1;in〉)" } } export: { let data#2 = { f1: "foo" } (〈1;#PutOut1〉 & { in: (〈2;#GetF1〉 & { in: 〈2;let data#2〉 }).out }).out } } } cue-lang-cue-db9cc73/cue/testdata/eval/cycles_ref.txtar000066400000000000000000000020211474664451600232110ustar00rootroot00000000000000-- in.cue -- a: b + 100 b: a - 100 a: 200 c: d & {b: 2} d: e e: {a: 1} e: c -- out/eval/stats -- Leaks: 0 Freed: 12 Reused: 7 Allocs: 5 Retain: 3 Unifications: 12 Conjuncts: 24 Disjuncts: 15 -- out/evalalpha -- (struct){ a: (int){ 200 } b: (int){ 100 } c: (struct){ b: (int){ 2 } a: (int){ 1 } } d: ~(e) e: (struct){ a: (int){ 1 } b: (int){ 2 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -5,10 +5,7 @@ b: (int){ 2 } a: (int){ 1 } } - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } + d: ~(e) e: (struct){ a: (int){ 1 } b: (int){ 2 } -- out/eval -- (struct){ a: (int){ 200 } b: (int){ 100 } c: (struct){ b: (int){ 2 } a: (int){ 1 } } d: (struct){ a: (int){ 1 } b: (int){ 2 } } e: (struct){ a: (int){ 1 } b: (int){ 2 } } } -- out/compile -- --- in.cue { a: (〈0;b〉 + 100) b: (〈0;a〉 - 100) a: 200 c: (〈0;d〉 & { b: 2 }) d: 〈0;e〉 e: { a: 1 } e: 〈0;c〉 } cue-lang-cue-db9cc73/cue/testdata/eval/discontinuous.txtar000066400000000000000000000032401474664451600240050ustar00rootroot00000000000000This test tests a case where a child node needs to be evaluated before evaluating a parent has completed. -- in.cue -- a: [for c in foo.bar.baz { c }] a: [{name: "http"}] foo: { x.D bar: baz: [{port: 8080}] } x: { D: bar: DSpec DSpec: {} } -- out/compile -- --- in.cue { a: [ for _, c in 〈1;foo〉.bar.baz { 〈1;c〉 }, ] a: [ { name: "http" }, ] foo: { 〈1;x〉.D bar: { baz: [ { port: 8080 }, ] } } x: { D: { bar: 〈1;DSpec〉 } DSpec: {} } } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 5 Allocs: 9 Retain: 9 Unifications: 14 Conjuncts: 23 Disjuncts: 23 -- out/evalalpha -- (struct){ a: (#list){ 0: (struct){ name: (string){ "http" } port: (int){ 8080 } } } foo: (struct){ bar: (struct){ baz: (#list){ 0: (struct){ port: (int){ 8080 } } } } } x: (struct){ D: (struct){ bar: (struct){ } } DSpec: (struct){ } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,8 +1,8 @@ (struct){ a: (#list){ 0: (struct){ - port: (int){ 8080 } name: (string){ "http" } + port: (int){ 8080 } } } foo: (struct){ -- diff/explanation -- Reordering. -- out/eval -- (struct){ a: (#list){ 0: (struct){ port: (int){ 8080 } name: (string){ "http" } } } foo: (struct){ bar: (struct){ baz: (#list){ 0: (struct){ port: (int){ 8080 } } } } } x: (struct){ D: (struct){ bar: (struct){ } } DSpec: (struct){ } } } cue-lang-cue-db9cc73/cue/testdata/eval/disjunctions.txtar000066400000000000000000000741241474664451600236240ustar00rootroot00000000000000-- in.cue -- a: *1 | int aa: *1 | *2 | int b: { name: "int" val: int } | { name: "str" val: string } d: b & {val: 3} c: b & {name: "int", val: 3} e: b & {val: "foo"} f: b & {name: "str", val: 3} // Disjunct elimination based on type. e1: { a: null | {bar: 2} b: (a & {}).bar } d1: { a: (null | {c: 1}) & {} b: {} & (null | {c: 1}) } d2: { a: ([...] | {c: 1}) & {} b: {} & ([...] | {c: 1}) } d3: { a: (string | {c: 1}) & {} b: {} & (string | {c: 1}) } d4: { a: (string | {c: 1}) & {} b: {} & (string | {c: 1}) } d5: { a: (number | {c: 1}) & {} b: {} & (number | {c: 1}) } d6: { a: (int | {c: 1}) & {} b: {} & (int | {c: 1}) } t10: { schema: test schema: string | {name: string} #A: {string | {name: string}} test: name: "Test" test: #A } t10: { schema: string | {name: string} schema: test #A: {string | {name: string}} test: name: "Test" test: #A } t10: { #A: {string | {name: string}} test: name: "Test" test: #A schema: string | {name: string} schema: test } t11: { a: #A a: b b: #A & ["b"] #A: ["a" | "b"] | {} } t11: { b: #A & ["b"] #A: ["a" | "b"] | {} a: b a: #A } cross: { a: *"word" | string a: string | *"word" } d100: { // Should we allow a selector to imply a struct or list? Would be convenient. // This would be a spec change. Disallow for now. i: null | {bar: 2} j: i.bar } issue641: { #A: { type: "a" x: "" } #B: { type: "b" x: string } #C: { b: #A | #B } e: [string]: #C & { b: #A | #B } e: foobar: #C & { b: #B & { x: "foobar" } } } -- issue3406.cue -- issue3406: { out: d & { d } d: kind: "foo" | "bar" d: { kind: "foo" } | { kind: "bar" } } -- issue3411.cue -- issue3411: { x: y?: [...string] x: {y: ["foo"]} | *{y: ["bar"]} } -- issue3490.cue -- issue3490: nested: p1: { ("a"|"b") | "b" "a"|"b" } issue3490: nested: p2: { "a"|"b" ("a"|"b") | "b" } issue3490: full: { data: [...#Schema] data: [#Schema & {}] #Schema: { runs?: "foo" | ([#D1] | [#D1, #D2]) #D1: "d1" #D2: "d2" } } -- issue3434.cue -- issue3434: t1: { ({} | {}) {["x"]: 1} {["y"]: 2} } issue3434: full: { out: #Schema & { steps: [{run: "example"}] } #Schema: { steps: [...{run: string}] #matrixConfig: string | [...#matrixConfig] matrix?: ({...} | string) & { {[=~"^foo"]: [...{[string]: #matrixConfig}]} {[=~"^bar"]: [...#matrixConfig] | string} } } } -- issue3597.cue -- issue3597: t1: { #Schema: { _ok: bool {} | { _ok: true let Ok = _ok {} | {x: Ok} } } [string]: #Schema foo: bar bar: {} } issue3597: t2: { ok: true X: _ | { let Ok = ok _ | {x: Ok} } foo: X & {X} } -- dependencies.cue -- issue3606: { data: { notAllowed: true } & #S #S: string | {} } issue3672: { #A: string | {y: true} #B: #A | {a: "append"} | {b: "prepend"} #fn: { #C: #B #out: x: [...#C] } // The unification inline appears to be critical #def: (#fn & {}).#out v: #def v: x: [{y: true}] // Should be one element } issue3681: { // Order dependent! These two fields need to go first. out: one: #strDefaultDef out: two: "\(strDefault)" strDefault: *"fallback" | string #strDefaultDef: strDefault } issue3699: { reduced: p1: { y: { if x.z { 1 } } x: *{z: true} | {} } reduced: p2: { y: { if x.z { 1 } } x: *{z: true} | {} } reduced: full: { _res: { _fooTrue: {} | *{foo: true} _msgSwitch: [ if _fooTrue.foo { msg: "foo" }, { msg: "bar" }, ][0] out: _msgSwitch.msg } let res = { out: (_res & {}).out } out: res.out } } -- out/eval/stats -- Leaks: 22 Freed: 673 Reused: 659 Allocs: 36 Retain: 63 Unifications: 370 Conjuncts: 1296 Disjuncts: 708 -- out/evalalpha -- Errors: f: 2 errors in empty disjunction: f.name: conflicting values "int" and "str": ./in.cue:5:8 ./in.cue:15:15 f.val: conflicting values 3 and string (mismatched types int and string): ./in.cue:9:8 ./in.cue:15:27 issue3606.data: 2 errors in empty disjunction: issue3606.data: conflicting values string and {notAllowed:true} (mismatched types string and struct): ./dependencies.cue:2:8 ./dependencies.cue:6:6 issue3606.data.notAllowed: field not allowed: ./dependencies.cue:3:3 Result: (_|_){ // [eval] issue3606: (_|_){ // [eval] data: (_|_){ // [eval] issue3606.data: 2 errors in empty disjunction: // issue3606.data: conflicting values string and {notAllowed:true} (mismatched types string and struct): // ./dependencies.cue:2:8 // ./dependencies.cue:6:6 // issue3606.data.notAllowed: field not allowed: // ./dependencies.cue:3:3 notAllowed: (bool){ true } } #S: ((string|struct)){ |((string){ string }, (#struct){ }) } } issue3672: (struct){ #A: ((string|struct)){ |((string){ string }, (#struct){ y: (bool){ true } }) } #B: ((string|struct)){ |((string){ string }, (#struct){ y: (bool){ true } }, (#struct){ a: (string){ "append" } }, (#struct){ b: (string){ "prepend" } }) } #fn: (#struct){ #C: ((string|struct)){ |((string){ string }, (#struct){ y: (bool){ true } }, (#struct){ a: (string){ "append" } }, (#struct){ b: (string){ "prepend" } }) } #out: (#struct){ x: (list){ } } } #def: (#struct){ x: (list){ } } v: (#struct){ x: (#list){ 0: (#struct){ y: (bool){ true } } } } } issue3681: (struct){ out: (struct){ one: (string){ |(*(string){ "fallback" }, (string){ string }) } two: (string){ "fallback" } } strDefault: (string){ |(*(string){ "fallback" }, (string){ string }) } #strDefaultDef: (string){ |(*(string){ "fallback" }, (string){ string }) } } issue3699: (struct){ reduced: (struct){ p1: (struct){ y: (int){ 1 } x: (struct){ |(*(struct){ z: (bool){ true } }, (struct){ }) } } p2: (struct){ y: (int){ 1 } x: (struct){ |(*(struct){ z: (bool){ true } }, (struct){ }) } } full: (struct){ _res: (struct){ _fooTrue: (struct){ |(*(struct){ foo: (bool){ true } }, (struct){ }) } _msgSwitch: (struct){ msg: (string){ "foo" } } out: (string){ "foo" } } let res#1 = (struct){ out: (string){ "foo" } } out: (string){ "foo" } } } } a: (int){ |(*(int){ 1 }, (int){ int }) } aa: (int){ |(*(int){ 1 }, *(int){ 2 }, (int){ int }) } b: (struct){ |((struct){ name: (string){ "int" } val: (int){ int } }, (struct){ name: (string){ "str" } val: (string){ string } }) } d: (struct){ val: (int){ 3 } name: (string){ "int" } } c: (struct){ name: (string){ "int" } val: (int){ 3 } } e: (struct){ val: (string){ "foo" } name: (string){ "str" } } f: (_|_){ // [eval] f: 2 errors in empty disjunction: // f.name: conflicting values "int" and "str": // ./in.cue:5:8 // ./in.cue:15:15 // f.val: conflicting values 3 and string (mismatched types int and string): // ./in.cue:9:8 // ./in.cue:15:27 name: (string){ "str" } val: (int){ 3 } } e1: (struct){ a: ((null|struct)){ |((null){ null }, (struct){ bar: (int){ 2 } }) } b: (int){ 2 } } d1: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d2: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d3: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d4: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d5: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d6: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t10: (struct){ schema: (#struct){ name: (string){ "Test" } } #A: ((string|struct)){ |((string){ string }, (#struct){ name: (string){ string } }) } test: (#struct){ name: (string){ "Test" } } } t11: (struct){ a: (#list){ 0: (string){ "b" } } b: (#list){ 0: (string){ "b" } } #A: ((list|struct)){ |((#list){ 0: (string){ |((string){ "a" }, (string){ "b" }) } }, (#struct){ }) } } cross: (struct){ a: (string){ |(*(string){ "word" }, (string){ string }) } } d100: (struct){ i: ((null|struct)){ |((null){ null }, (struct){ bar: (int){ 2 } }) } j: (_|_){ // [incomplete] d100.j: unresolved disjunction null | {bar:2} (type (null|struct)): // ./in.cue:106:5 } } issue641: (struct){ #A: (#struct){ type: (string){ "a" } x: (string){ "" } } #B: (#struct){ type: (string){ "b" } x: (string){ string } } #C: (#struct){ b: (#struct){ |((#struct){ type: (string){ "a" } x: (string){ "" } }, (#struct){ type: (string){ "b" } x: (string){ string } }) } } e: (struct){ foobar: (#struct){ b: (#struct){ x: (string){ "foobar" } type: (string){ "b" } } } } } issue3406: (struct){ out: (struct){ |((struct){ kind: (string){ "foo" } }, (struct){ kind: (string){ "bar" } }) } d: (struct){ |((struct){ kind: (string){ "foo" } }, (struct){ kind: (string){ "bar" } }) } } issue3411: (struct){ x: (struct){ |(*(struct){ y: (#list){ 0: (string){ "bar" } } }, (struct){ y: (#list){ 0: (string){ "foo" } } }) } } issue3434: (struct){ t1: (struct){ } full: (struct){ out: (#struct){ steps: (#list){ 0: (#struct){ run: (string){ "example" } } } #matrixConfig: ((string|list)){ |((string){ string }, (list){ }) } matrix?: (#struct){ } } #Schema: (#struct){ steps: (list){ } #matrixConfig: ((string|list)){ |((string){ string }, (list){ }) } matrix?: (#struct){ } } } } issue3490: (struct){ nested: (struct){ p1: (string){ |((string){ "a" }, (string){ "b" }) } p2: (string){ |((string){ "a" }, (string){ "b" }) } } full: (struct){ data: (#list){ 0: (#struct){ runs?: ((string|list)){ |((string){ "foo" }, (#list){ 0: (string){ "d1" } }, (#list){ 0: (string){ "d1" } 1: (string){ "d2" } }) } #D1: (string){ "d1" } #D2: (string){ "d2" } } } #Schema: (#struct){ runs?: ((string|list)){ |((string){ "foo" }, (#list){ 0: (string){ "d1" } }, (#list){ 0: (string){ "d1" } 1: (string){ "d2" } }) } #D1: (string){ "d1" } #D2: (string){ "d2" } } } } issue3597: (struct){ t1: (struct){ #Schema: (#struct){ |((#struct){ _ok: (bool){ bool } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } x: (bool){ true } }) } foo: (#struct){ |((#struct){ _ok: (bool){ bool } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } }, (#struct){ _ok: (bool){ true } let Ok#2multi = 〈0;_ok〉 x: (bool){ true } }) } bar: (#struct){ |((#struct){ _ok: (bool){ bool } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } x: (bool){ true } }) } } t2: (struct){ ok: (bool){ true } X: (_){ |((_){ _ }, (_){ _ let Ok#3 = (bool){ true } }, (struct){ let Ok#3 = (bool){ true } x: (bool){ true } }) } foo: (_){ |((_){ _ }, (_){ _ let Ok#3 = (bool){ true } }, (struct){ let Ok#3 = (bool){ true } x: (bool){ true } }) } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,11 +2,9 @@ f: 2 errors in empty disjunction: f.name: conflicting values "int" and "str": ./in.cue:5:8 - ./in.cue:15:4 ./in.cue:15:15 f.val: conflicting values 3 and string (mismatched types int and string): ./in.cue:9:8 - ./in.cue:15:4 ./in.cue:15:27 issue3606.data: 2 errors in empty disjunction: issue3606.data: conflicting values string and {notAllowed:true} (mismatched types string and struct): @@ -14,8 +12,6 @@ ./dependencies.cue:6:6 issue3606.data.notAllowed: field not allowed: ./dependencies.cue:3:3 - ./dependencies.cue:4:6 - ./dependencies.cue:6:15 Result: (_|_){ @@ -29,14 +25,7 @@ // ./dependencies.cue:6:6 // issue3606.data.notAllowed: field not allowed: // ./dependencies.cue:3:3 - // ./dependencies.cue:4:6 - // ./dependencies.cue:6:15 - notAllowed: (_|_){ - // [eval] issue3606.data.notAllowed: field not allowed: - // ./dependencies.cue:3:3 - // ./dependencies.cue:4:6 - // ./dependencies.cue:6:15 - } + notAllowed: (bool){ true } } #S: ((string|struct)){ |((string){ string }, (#struct){ }) } @@ -144,19 +133,12 @@ // [eval] f: 2 errors in empty disjunction: // f.name: conflicting values "int" and "str": // ./in.cue:5:8 - // ./in.cue:15:4 // ./in.cue:15:15 // f.val: conflicting values 3 and string (mismatched types int and string): // ./in.cue:9:8 - // ./in.cue:15:4 // ./in.cue:15:27 name: (string){ "str" } - val: (_|_){ - // [eval] f.val: conflicting values 3 and string (mismatched types int and string): - // ./in.cue:9:8 - // ./in.cue:15:4 - // ./in.cue:15:27 - } + val: (int){ 3 } } e1: (struct){ a: ((null|struct)){ |((null){ null }, (struct){ @@ -268,8 +250,8 @@ e: (struct){ foobar: (#struct){ b: (#struct){ - type: (string){ "b" } x: (string){ "foobar" } + type: (string){ "b" } } } } -- diff/todo/p1 -- issue3597.t1.foo: duplicate disjunct -- diff/todo/p3 -- Missing error positions. It is probably okay to show name and val fields with original values, as long as it is made clear that f does not unify with disjunctions and positions are conveyed properly. -- out/eval -- Errors: f: 2 errors in empty disjunction: f.name: conflicting values "int" and "str": ./in.cue:5:8 ./in.cue:15:4 ./in.cue:15:15 f.val: conflicting values 3 and string (mismatched types int and string): ./in.cue:9:8 ./in.cue:15:4 ./in.cue:15:27 issue3606.data: 2 errors in empty disjunction: issue3606.data: conflicting values string and {notAllowed:true} (mismatched types string and struct): ./dependencies.cue:2:8 ./dependencies.cue:6:6 issue3606.data.notAllowed: field not allowed: ./dependencies.cue:3:3 ./dependencies.cue:4:6 ./dependencies.cue:6:15 Result: (_|_){ // [eval] issue3606: (_|_){ // [eval] data: (_|_){ // [eval] issue3606.data: 2 errors in empty disjunction: // issue3606.data: conflicting values string and {notAllowed:true} (mismatched types string and struct): // ./dependencies.cue:2:8 // ./dependencies.cue:6:6 // issue3606.data.notAllowed: field not allowed: // ./dependencies.cue:3:3 // ./dependencies.cue:4:6 // ./dependencies.cue:6:15 notAllowed: (_|_){ // [eval] issue3606.data.notAllowed: field not allowed: // ./dependencies.cue:3:3 // ./dependencies.cue:4:6 // ./dependencies.cue:6:15 } } #S: ((string|struct)){ |((string){ string }, (#struct){ }) } } issue3672: (struct){ #A: ((string|struct)){ |((string){ string }, (#struct){ y: (bool){ true } }) } #B: ((string|struct)){ |((string){ string }, (#struct){ y: (bool){ true } }, (#struct){ a: (string){ "append" } }, (#struct){ b: (string){ "prepend" } }) } #fn: (#struct){ #C: ((string|struct)){ |((string){ string }, (#struct){ y: (bool){ true } }, (#struct){ a: (string){ "append" } }, (#struct){ b: (string){ "prepend" } }) } #out: (#struct){ x: (list){ } } } #def: (#struct){ x: (list){ } } v: (#struct){ x: (#list){ 0: (#struct){ y: (bool){ true } } } } } issue3681: (struct){ out: (struct){ one: (string){ |(*(string){ "fallback" }, (string){ string }) } two: (string){ "fallback" } } strDefault: (string){ |(*(string){ "fallback" }, (string){ string }) } #strDefaultDef: (string){ |(*(string){ "fallback" }, (string){ string }) } } issue3699: (struct){ reduced: (struct){ p1: (struct){ y: (int){ 1 } x: (struct){ |(*(struct){ z: (bool){ true } }, (struct){ }) } } p2: (struct){ y: (int){ 1 } x: (struct){ |(*(struct){ z: (bool){ true } }, (struct){ }) } } full: (struct){ _res: (struct){ _fooTrue: (struct){ |(*(struct){ foo: (bool){ true } }, (struct){ }) } _msgSwitch: (struct){ msg: (string){ "foo" } } out: (string){ "foo" } } let res#1 = (struct){ out: (string){ "foo" } } out: (string){ "foo" } } } } a: (int){ |(*(int){ 1 }, (int){ int }) } aa: (int){ |(*(int){ 1 }, *(int){ 2 }, (int){ int }) } b: (struct){ |((struct){ name: (string){ "int" } val: (int){ int } }, (struct){ name: (string){ "str" } val: (string){ string } }) } d: (struct){ val: (int){ 3 } name: (string){ "int" } } c: (struct){ name: (string){ "int" } val: (int){ 3 } } e: (struct){ val: (string){ "foo" } name: (string){ "str" } } f: (_|_){ // [eval] f: 2 errors in empty disjunction: // f.name: conflicting values "int" and "str": // ./in.cue:5:8 // ./in.cue:15:4 // ./in.cue:15:15 // f.val: conflicting values 3 and string (mismatched types int and string): // ./in.cue:9:8 // ./in.cue:15:4 // ./in.cue:15:27 name: (string){ "str" } val: (_|_){ // [eval] f.val: conflicting values 3 and string (mismatched types int and string): // ./in.cue:9:8 // ./in.cue:15:4 // ./in.cue:15:27 } } e1: (struct){ a: ((null|struct)){ |((null){ null }, (struct){ bar: (int){ 2 } }) } b: (int){ 2 } } d1: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d2: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d3: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d4: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d5: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } d6: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t10: (struct){ schema: (#struct){ name: (string){ "Test" } } #A: ((string|struct)){ |((string){ string }, (#struct){ name: (string){ string } }) } test: (#struct){ name: (string){ "Test" } } } t11: (struct){ a: (#list){ 0: (string){ "b" } } b: (#list){ 0: (string){ "b" } } #A: ((list|struct)){ |((#list){ 0: (string){ |((string){ "a" }, (string){ "b" }) } }, (#struct){ }) } } cross: (struct){ a: (string){ |(*(string){ "word" }, (string){ string }) } } d100: (struct){ i: ((null|struct)){ |((null){ null }, (struct){ bar: (int){ 2 } }) } j: (_|_){ // [incomplete] d100.j: unresolved disjunction null | {bar:2} (type (null|struct)): // ./in.cue:106:5 } } issue641: (struct){ #A: (#struct){ type: (string){ "a" } x: (string){ "" } } #B: (#struct){ type: (string){ "b" } x: (string){ string } } #C: (#struct){ b: (#struct){ |((#struct){ type: (string){ "a" } x: (string){ "" } }, (#struct){ type: (string){ "b" } x: (string){ string } }) } } e: (struct){ foobar: (#struct){ b: (#struct){ type: (string){ "b" } x: (string){ "foobar" } } } } } issue3406: (struct){ out: (struct){ |((struct){ kind: (string){ "foo" } }, (struct){ kind: (string){ "bar" } }) } d: (struct){ |((struct){ kind: (string){ "foo" } }, (struct){ kind: (string){ "bar" } }) } } issue3411: (struct){ x: (struct){ |(*(struct){ y: (#list){ 0: (string){ "bar" } } }, (struct){ y: (#list){ 0: (string){ "foo" } } }) } } issue3434: (struct){ t1: (struct){ } full: (struct){ out: (#struct){ steps: (#list){ 0: (#struct){ run: (string){ "example" } } } #matrixConfig: ((string|list)){ |((string){ string }, (list){ }) } matrix?: (#struct){ } } #Schema: (#struct){ steps: (list){ } #matrixConfig: ((string|list)){ |((string){ string }, (list){ }) } matrix?: (#struct){ } } } } issue3490: (struct){ nested: (struct){ p1: (string){ |((string){ "a" }, (string){ "b" }) } p2: (string){ |((string){ "a" }, (string){ "b" }) } } full: (struct){ data: (#list){ 0: (#struct){ runs?: ((string|list)){ |((string){ "foo" }, (#list){ 0: (string){ "d1" } }, (#list){ 0: (string){ "d1" } 1: (string){ "d2" } }) } #D1: (string){ "d1" } #D2: (string){ "d2" } } } #Schema: (#struct){ runs?: ((string|list)){ |((string){ "foo" }, (#list){ 0: (string){ "d1" } }, (#list){ 0: (string){ "d1" } 1: (string){ "d2" } }) } #D1: (string){ "d1" } #D2: (string){ "d2" } } } } issue3597: (struct){ t1: (struct){ #Schema: (#struct){ |((#struct){ _ok: (bool){ bool } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } x: (bool){ true } }) } foo: (#struct){ |((#struct){ _ok: (bool){ bool } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } }, (#struct){ _ok: (bool){ true } let Ok#2multi = 〈0;_ok〉 x: (bool){ true } }) } bar: (#struct){ |((#struct){ _ok: (bool){ bool } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } }, (#struct){ _ok: (bool){ true } let Ok#2 = (bool){ true } x: (bool){ true } }) } } t2: (struct){ ok: (bool){ true } X: (_){ |((_){ _ }, (_){ _ let Ok#3 = (bool){ true } }, (struct){ let Ok#3 = (bool){ true } x: (bool){ true } }) } foo: (_){ |((_){ _ }, (_){ _ let Ok#3 = (bool){ true } }, (struct){ let Ok#3 = (bool){ true } x: (bool){ true } }) } } } } -- out/compile -- --- dependencies.cue { issue3606: { data: ({ notAllowed: true } & 〈0;#S〉) #S: (string|{}) } issue3672: { #A: (string|{ y: true }) #B: (〈0;#A〉|{ a: "append" }|{ b: "prepend" }) #fn: { #C: 〈1;#B〉 #out: { x: [ ...〈2;#C〉, ] } } #def: (〈0;#fn〉 & {}).#out v: 〈0;#def〉 v: { x: [ { y: true }, ] } } issue3681: { out: { one: 〈1;#strDefaultDef〉 } out: { two: "\(〈1;strDefault〉)" } strDefault: (*"fallback"|string) #strDefaultDef: 〈0;strDefault〉 } issue3699: { reduced: { p1: { y: { if 〈1;x〉.z { 1 } } x: (*{ z: true }|{}) } } reduced: { p2: { y: { if 〈1;x〉.z { 1 } } x: (*{ z: true }|{}) } } reduced: { full: { _res: { _fooTrue: ({}|*{ foo: true }) _msgSwitch: [ if 〈1;_fooTrue〉.foo { msg: "foo" }, { msg: "bar" }, ][0] out: 〈0;_msgSwitch〉.msg } let res#1 = { out: (〈1;_res〉 & {}).out } out: 〈0;let res#1〉.out } } } } --- in.cue { a: (*1|int) aa: (*1|*2|int) b: ({ name: "int" val: int }|{ name: "str" val: string }) d: (〈0;b〉 & { val: 3 }) c: (〈0;b〉 & { name: "int" val: 3 }) e: (〈0;b〉 & { val: "foo" }) f: (〈0;b〉 & { name: "str" val: 3 }) e1: { a: (null|{ bar: 2 }) b: (〈0;a〉 & {}).bar } d1: { a: ((null|{ c: 1 }) & {}) b: ({} & (null|{ c: 1 })) } d2: { a: (([ ..., ]|{ c: 1 }) & {}) b: ({} & ([ ..., ]|{ c: 1 })) } d3: { a: ((string|{ c: 1 }) & {}) b: ({} & (string|{ c: 1 })) } d4: { a: ((string|{ c: 1 }) & {}) b: ({} & (string|{ c: 1 })) } d5: { a: ((number|{ c: 1 }) & {}) b: ({} & (number|{ c: 1 })) } d6: { a: ((int|{ c: 1 }) & {}) b: ({} & (int|{ c: 1 })) } t10: { schema: 〈0;test〉 schema: (string|{ name: string }) #A: { (string|{ name: string }) } test: { name: "Test" } test: 〈0;#A〉 } t10: { schema: (string|{ name: string }) schema: 〈0;test〉 #A: { (string|{ name: string }) } test: { name: "Test" } test: 〈0;#A〉 } t10: { #A: { (string|{ name: string }) } test: { name: "Test" } test: 〈0;#A〉 schema: (string|{ name: string }) schema: 〈0;test〉 } t11: { a: 〈0;#A〉 a: 〈0;b〉 b: (〈0;#A〉 & [ "b", ]) #A: ([ ("a"|"b"), ]|{}) } t11: { b: (〈0;#A〉 & [ "b", ]) #A: ([ ("a"|"b"), ]|{}) a: 〈0;b〉 a: 〈0;#A〉 } cross: { a: (*"word"|string) a: (string|*"word") } d100: { i: (null|{ bar: 2 }) j: 〈0;i〉.bar } issue641: { #A: { type: "a" x: "" } #B: { type: "b" x: string } #C: { b: (〈1;#A〉|〈1;#B〉) } e: { [string]: (〈1;#C〉 & { b: (〈2;#A〉|〈2;#B〉) }) } e: { foobar: (〈1;#C〉 & { b: (〈2;#B〉 & { x: "foobar" }) }) } } } --- issue3406.cue { issue3406: { out: (〈0;d〉 & { 〈1;d〉 }) d: { kind: ("foo"|"bar") } d: ({ kind: "foo" }|{ kind: "bar" }) } } --- issue3411.cue { issue3411: { x: { y?: [ ...string, ] } x: ({ y: [ "foo", ] }|*{ y: [ "bar", ] }) } } --- issue3434.cue { issue3434: { t1: { ({}|{}) { ["x"]: 1 } { ["y"]: 2 } } } issue3434: { full: { out: (〈0;#Schema〉 & { steps: [ { run: "example" }, ] }) #Schema: { steps: [ ...{ run: string }, ] #matrixConfig: (string|[ ...〈1;#matrixConfig〉, ]) matrix?: (({ ... }|string) & { { [=~"^foo"]: [ ...{ [string]: 〈4;#matrixConfig〉 }, ] } { [=~"^bar"]: ([ ...〈3;#matrixConfig〉, ]|string) } }) } } } } --- issue3490.cue { issue3490: { nested: { p1: { (("a"|"b")|"b") ("a"|"b") } } } issue3490: { nested: { p2: { ("a"|"b") (("a"|"b")|"b") } } } issue3490: { full: { data: [ ...〈1;#Schema〉, ] data: [ (〈1;#Schema〉 & {}), ] #Schema: { runs?: ("foo"|([ 〈1;#D1〉, ]|[ 〈1;#D1〉, 〈1;#D2〉, ])) #D1: "d1" #D2: "d2" } } } } --- issue3597.cue { issue3597: { t1: { #Schema: { _ok: bool ({}|{ _ok: true let Ok#2 = 〈0;_ok〉 ({}|{ x: 〈1;let Ok#2〉 }) }) } [string]: 〈0;#Schema〉 foo: 〈0;bar〉 bar: {} } } issue3597: { t2: { ok: true X: (_|{ let Ok#3 = 〈1;ok〉 (_|{ x: 〈1;let Ok#3〉 }) }) foo: (〈0;X〉 & { 〈1;X〉 }) } } } cue-lang-cue-db9cc73/cue/testdata/eval/dynamic_field.txtar000066400000000000000000000204351474664451600236730ustar00rootroot00000000000000-- in.cue -- a: "foo" "\(a)": b: c: d: e e: 2 b: "bar" X="\(b)": { a: 1 } c: X withError: { issue799: {key: int32} & {"\(1 & 2)": 123} } parenExprRefParent: { a: (x): {} x: "foo" } parenExprRefEqual: { (x): {} x: "foo" } chainedResolution: { p1: { (p1.baz): "bar" (p1.foo): "baz" baz: "foo" } p2: { (p2.baz): "bar" baz: "foo" (p2.foo): "baz" } p3: { baz: "foo" (p3.baz): "bar" (p3.foo): "baz" } p4: { (p4.foo): "baz" (p4.baz): "bar" baz: "foo" } p5: { (p5.foo): "baz" baz: "foo" (p5.baz): "bar" } p6: { baz: "foo" (p6.foo): "baz" (p6.baz): "bar" } } // Issue #1407 noCycleError: { foo: [_]: { #ID: "\(string)" } foo: bar: entries: (foo.baz.#ID): true foo: baz: {} } -- constraints.cue -- constraints: { t1: "foo" t2: "bar" (t1)?: (t2)!: 3 } -- out/eval/stats -- Leaks: 2 Freed: 59 Reused: 52 Allocs: 9 Retain: 11 Unifications: 61 Conjuncts: 77 Disjuncts: 66 -- out/evalalpha -- Errors: invalid interpolation: conflicting values 2 and 1: ./in.cue:12:28 ./in.cue:12:31 ./in.cue:12:35 Result: (_|_){ // [eval] constraints: (struct){ t1: (string){ "foo" } t2: (string){ "bar" } foo?: (struct){ bar!: (int){ 3 } } } a: (string){ "foo" } e: (int){ 2 } b: (string){ "bar" } c: ~(bar) withError: (_|_){ // [eval] issue799: (_|_){ // [eval] invalid interpolation: conflicting values 2 and 1: // ./in.cue:12:28 // ./in.cue:12:31 // ./in.cue:12:35 key: (int){ &(>=-2147483648, <=2147483647, int) } } } parenExprRefParent: (struct){ a: (struct){ foo: (struct){ } } x: (string){ "foo" } } parenExprRefEqual: (struct){ x: (string){ "foo" } foo: (struct){ } } chainedResolution: (struct){ p1: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p2: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p3: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p4: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p5: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p6: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } } noCycleError: (struct){ foo: (struct){ bar: (struct){ entries: (_|_){ // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 // noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(invalid interpolation: noCycleError.foo.baz.#ID: non-concrete value string (type string)): // ./in.cue:61:22 } #ID: (_|_){ // [incomplete] noCycleError.foo.bar.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 } } baz: (struct){ #ID: (_|_){ // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 } } } } bar: (struct){ a: (int){ 1 } } foo: (struct){ b: (struct){ c: (struct){ d: (int){ 2 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -17,9 +17,7 @@ a: (string){ "foo" } e: (int){ 2 } b: (string){ "bar" } - c: (struct){ - a: (int){ 1 } - } + c: ~(bar) withError: (_|_){ // [eval] issue799: (_|_){ @@ -81,6 +79,8 @@ // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 + // noCycleError.foo.bar.entries: key value of dynamic field must be concrete, found _|_(invalid interpolation: noCycleError.foo.baz.#ID: non-concrete value string (type string)): + // ./in.cue:61:22 } #ID: (_|_){ // [incomplete] noCycleError.foo.bar.#ID: invalid interpolation: non-concrete value string (type string): @@ -97,6 +97,9 @@ } } } + bar: (struct){ + a: (int){ 1 } + } foo: (struct){ b: (struct){ c: (struct){ @@ -104,7 +107,4 @@ } } } - bar: (struct){ - a: (int){ 1 } - } } -- diff/todo/p2 -- Added near-duplicate message -- out/eval -- Errors: invalid interpolation: conflicting values 2 and 1: ./in.cue:12:28 ./in.cue:12:31 ./in.cue:12:35 Result: (_|_){ // [eval] constraints: (struct){ t1: (string){ "foo" } t2: (string){ "bar" } foo?: (struct){ bar!: (int){ 3 } } } a: (string){ "foo" } e: (int){ 2 } b: (string){ "bar" } c: (struct){ a: (int){ 1 } } withError: (_|_){ // [eval] issue799: (_|_){ // [eval] invalid interpolation: conflicting values 2 and 1: // ./in.cue:12:28 // ./in.cue:12:31 // ./in.cue:12:35 key: (int){ &(>=-2147483648, <=2147483647, int) } } } parenExprRefParent: (struct){ a: (struct){ foo: (struct){ } } x: (string){ "foo" } } parenExprRefEqual: (struct){ x: (string){ "foo" } foo: (struct){ } } chainedResolution: (struct){ p1: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p2: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p3: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p4: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p5: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } p6: (struct){ baz: (string){ "foo" } foo: (string){ "bar" } bar: (string){ "baz" } } } noCycleError: (struct){ foo: (struct){ bar: (struct){ entries: (_|_){ // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 } #ID: (_|_){ // [incomplete] noCycleError.foo.bar.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 } } baz: (struct){ #ID: (_|_){ // [incomplete] noCycleError.foo.baz.#ID: invalid interpolation: non-concrete value string (type string): // ./in.cue:59:8 // ./in.cue:59:11 } } } } foo: (struct){ b: (struct){ c: (struct){ d: (int){ 2 } } } } bar: (struct){ a: (int){ 1 } } } -- out/compile -- --- constraints.cue { constraints: { t1: "foo" t2: "bar" 〈0;t1〉?: { 〈1;t2〉!: 3 } } } --- in.cue { a: "foo" "\(〈0;a〉)": { b: { c: { d: 〈3;e〉 } } } e: 2 b: "bar" "\(〈0;b〉)": { a: 1 } c: 〈0;("\(〈0;b〉)")〉 withError: { issue799: ({ key: &(int, >=-2147483648, <=2147483647) } & { "\((1 & 2))": 123 }) } parenExprRefParent: { a: { 〈1;x〉: {} } x: "foo" } parenExprRefEqual: { 〈0;x〉: {} x: "foo" } chainedResolution: { p1: { 〈1;p1〉.baz: "bar" 〈1;p1〉.foo: "baz" baz: "foo" } p2: { 〈1;p2〉.baz: "bar" baz: "foo" 〈1;p2〉.foo: "baz" } p3: { baz: "foo" 〈1;p3〉.baz: "bar" 〈1;p3〉.foo: "baz" } p4: { 〈1;p4〉.foo: "baz" 〈1;p4〉.baz: "bar" baz: "foo" } p5: { 〈1;p5〉.foo: "baz" baz: "foo" 〈1;p5〉.baz: "bar" } p6: { baz: "foo" 〈1;p6〉.foo: "baz" 〈1;p6〉.baz: "bar" } } noCycleError: { foo: { [_]: { #ID: "\(string)" } } foo: { bar: { entries: { 〈3;foo〉.baz.#ID: true } } } foo: { baz: {} } } } cue-lang-cue-db9cc73/cue/testdata/eval/embed.txtar000066400000000000000000000031321474664451600221530ustar00rootroot00000000000000-- in.cue -- #A: { Common ... } Common: { a: int b: int } x: #A x: { c: int } #B: { if true { a: int } ... } y: #B y: { c: int } -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 12 Allocs: 4 Retain: 1 Unifications: 16 Conjuncts: 32 Disjuncts: 17 -- out/evalalpha -- (struct){ #A: (#struct){ a: (int){ int } b: (int){ int } } Common: (struct){ a: (int){ int } b: (int){ int } } x: (#struct){ c: (int){ int } a: (int){ int } b: (int){ int } } #B: (#struct){ a: (int){ int } } y: (#struct){ c: (int){ int } a: (int){ int } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -8,15 +8,15 @@ b: (int){ int } } x: (#struct){ - a: (int){ int } - b: (int){ int } - c: (int){ int } + c: (int){ int } + a: (int){ int } + b: (int){ int } } #B: (#struct){ a: (int){ int } } y: (#struct){ - a: (int){ int } - c: (int){ int } + c: (int){ int } + a: (int){ int } } } -- diff/explanation -- Reordering -- out/eval -- (struct){ #A: (#struct){ a: (int){ int } b: (int){ int } } Common: (struct){ a: (int){ int } b: (int){ int } } x: (#struct){ a: (int){ int } b: (int){ int } c: (int){ int } } #B: (#struct){ a: (int){ int } } y: (#struct){ a: (int){ int } c: (int){ int } } } -- out/compile -- --- in.cue { #A: { 〈1;Common〉 ... } Common: { a: int b: int } x: 〈0;#A〉 x: { c: int } #B: { if true { a: int } ... } y: 〈0;#B〉 y: { c: int } } cue-lang-cue-db9cc73/cue/testdata/eval/errunifiy.txtar000066400000000000000000000011511474664451600231120ustar00rootroot00000000000000Incomplete errors should not unify with values. -- in.cue -- a: or([]) a: "t" b: _|_ b: "t" -- out/eval/stats -- Leaks: 5 Freed: 3 Reused: 1 Allocs: 7 Retain: 5 Unifications: 8 Conjuncts: 14 Disjuncts: 8 -- out/eval -- Errors: explicit error (_|_ literal) in source: ./in.cue:4:4 Result: (_|_){ // [user] a: (_|_){ // [incomplete] empty list in call to or: // ./in.cue:1:4 } b: (_|_){ // [user] explicit error (_|_ literal) in source: // ./in.cue:4:4 } } -- out/compile -- --- in.cue { a: or([]) a: "t" b: _|_(explicit error (_|_ literal) in source) b: "t" } cue-lang-cue-db9cc73/cue/testdata/eval/expressions.txtar000066400000000000000000000005231474664451600234620ustar00rootroot00000000000000-- in.cue -- a: 1 b: 1 + 2 c: 3 - 1 d: 5 rem 3 -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 3 Allocs: 2 Retain: 0 Unifications: 5 Conjuncts: 5 Disjuncts: 5 -- out/eval -- (struct){ a: (int){ 1 } b: (int){ 3 } c: (int){ 2 } d: (int){ 2 } } -- out/compile -- --- in.cue { a: 1 b: (1 + 2) c: (3 - 1) d: (5 rem 3) } cue-lang-cue-db9cc73/cue/testdata/eval/fields.txtar000066400000000000000000000037711474664451600223560ustar00rootroot00000000000000-- in.cue -- bulkToSelf: { a: { foo: [string]: int foo: bar: "3" // error } } intField: { (2): string } -- out/compile -- --- in.cue { bulkToSelf: { a: { foo: { [string]: int } foo: { bar: "3" } } } intField: { 2: string } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 2 Allocs: 5 Retain: 0 Unifications: 7 Conjuncts: 9 Disjuncts: 7 -- out/evalalpha -- Errors: bulkToSelf.a.foo.bar: conflicting values "3" and int (mismatched types string and int): ./in.cue:3:18 ./in.cue:4:18 intField: integer fields not supported: ./in.cue:8:3 Result: (_|_){ // [eval] bulkToSelf: (_|_){ // [eval] a: (_|_){ // [eval] foo: (_|_){ // [eval] bar: (_|_){ // [eval] bulkToSelf.a.foo.bar: conflicting values "3" and int (mismatched types string and int): // ./in.cue:3:18 // ./in.cue:4:18 } } } } intField: (_|_){ // [eval] intField: integer fields not supported: // ./in.cue:8:3 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -25,6 +25,5 @@ intField: (_|_){ // [eval] intField: integer fields not supported: // ./in.cue:8:3 - 2: (string){ string } } } -- diff/explanation -- Not including illegal field. Seems fine. -- out/eval -- Errors: bulkToSelf.a.foo.bar: conflicting values "3" and int (mismatched types string and int): ./in.cue:3:18 ./in.cue:4:18 intField: integer fields not supported: ./in.cue:8:3 Result: (_|_){ // [eval] bulkToSelf: (_|_){ // [eval] a: (_|_){ // [eval] foo: (_|_){ // [eval] bar: (_|_){ // [eval] bulkToSelf.a.foo.bar: conflicting values "3" and int (mismatched types string and int): // ./in.cue:3:18 // ./in.cue:4:18 } } } } intField: (_|_){ // [eval] intField: integer fields not supported: // ./in.cue:8:3 2: (string){ string } } } cue-lang-cue-db9cc73/cue/testdata/eval/incomplete.txtar000066400000000000000000000124321474664451600232410ustar00rootroot00000000000000-- in.cue -- s: string e1: s + s e2: >"bar" & s // okay e3: >s & "foo" // not okay e3b: >s e4: >e1 & s e5: =5 } a: int okay: (>10 & "bar" } e3: (_|_){ // [incomplete] e3: non-concrete value s for bound >: // ./in.cue:5:7 } e3b: (_|_){ // [incomplete] e3b: non-concrete value s for bound >: // ./in.cue:6:7 } e4: (_|_){ // [incomplete] e1: non-concrete value string in operand to +: // ./in.cue:3:6 // ./in.cue:1:4 } e5: (_|_){ // [cycle] cycle error } E: (struct){ a: (_|_){ // [cycle] cycle error: // ./in.cue:12:5 } b: (_|_){ // [cycle] cycle error: // ./in.cue:13:5 } c: (_|_){ // [cycle] cycle error: // ./in.cue:12:5 // cycle error: // ./in.cue:13:5 } } a: (int){ int } okay: (_|_){ // [incomplete] non-concrete value a for bound <: // ./in.cue:18:15 } issue1837: (struct){ p1: (struct){ context: (struct){ } x: (_|_){ // [incomplete] issue1837.p1.x: undefined field: b: // ./in.cue:25:14 } message: (string){ "a" } } p2: (struct){ message: (string){ "a" } x: (_|_){ // [incomplete] issue1837.p2.x: undefined field: b: // ./in.cue:34:14 } context: (struct){ } } p3: (struct){ message: (string){ "a" } context: (struct){ } x: (_|_){ // [incomplete] issue1837.p3.x: undefined field: b: // ./in.cue:42:14 } } } } -- out/evalalpha -- (struct){ s: (string){ string } e1: (_|_){ // [incomplete] e1: non-concrete value string in operand to +: // ./in.cue:3:6 // ./in.cue:1:4 } e2: (string){ >"bar" } e3: (_|_){ // [incomplete] e3: non-concrete value s for bound >: // ./in.cue:5:7 } e3b: (_|_){ // [incomplete] e3b: non-concrete value s for bound >: // ./in.cue:6:7 } e4: (_|_){ // [incomplete] e1: non-concrete value string in operand to +: // ./in.cue:3:6 // ./in.cue:1:4 } e5: (_|_){ // [cycle] cycle error } E: (struct){ a: (_|_){ // [cycle] cycle error: // ./in.cue:13:5 // cycle error: // ./in.cue:14:5 } b: (_|_){ // [cycle] cycle error: // ./in.cue:13:5 } c: (_|_){ // [cycle] cycle error: // ./in.cue:14:5 } } a: (int){ int } okay: (_|_){ // [incomplete] non-concrete value a for bound <: // ./in.cue:18:15 } issue1837: (struct){ p1: (struct){ context: (struct){ } x: (_|_){ // [incomplete] issue1837.p1.x: undefined field: b: // ./in.cue:25:14 } message: (string){ "a" } } p2: (struct){ message: (string){ "a" } x: (_|_){ // [incomplete] issue1837.p2.x: undefined field: b: // ./in.cue:34:14 } context: (struct){ } } p3: (struct){ message: (string){ "a" } context: (struct){ } x: (_|_){ // [incomplete] issue1837.p3.x: undefined field: b: // ./in.cue:42:14 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -25,7 +25,9 @@ E: (struct){ a: (_|_){ // [cycle] cycle error: - // ./in.cue:12:5 + // ./in.cue:13:5 + // cycle error: + // ./in.cue:14:5 } b: (_|_){ // [cycle] cycle error: @@ -33,9 +35,7 @@ } c: (_|_){ // [cycle] cycle error: - // ./in.cue:12:5 - // cycle error: - // ./in.cue:13:5 + // ./in.cue:14:5 } } a: (int){ int } -- out/compile -- --- in.cue { s: string e1: (〈0;s〉 + 〈0;s〉) e2: (>"bar" & 〈0;s〉) e3: (>〈0;s〉 & "foo") e3b: >〈0;s〉 e4: (>〈0;e1〉 & 〈0;s〉) e5: (<〈0;e5〉 & 〈0;s〉) E: { a: (〈0;c〉 - 〈0;b〉) b: (〈0;c〉 - 〈0;a〉) c: ((〈0;a〉 + 〈0;b〉) & >=5) } a: int okay: ((>10 & <〈0;a〉) + 3) issue1837: { p1: { context: {} x: 〈0;context〉.b if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { message: "a" } } p2: { if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { message: "a" } x: 〈0;context〉.b context: {} } p3: { if (〈0;x〉 == _|_(explicit error (_|_ literal) in source)) { message: "a" } context: {} x: 〈0;context〉.b } } } cue-lang-cue-db9cc73/cue/testdata/eval/incompleteperm.txtar000066400000000000000000000043701474664451600241270ustar00rootroot00000000000000// Issue #742 // Issue #405 -- in.cue -- // Issue #129 permanentlyIncompleteOperands: { a: string + ":" + string a: "golang/go:1.13.5" } permanentlyIncompleteOperandsNested: { a: (int + 1) + (int + 1) } permanentlyIncompleteOperandsDisjunct: { a: (int + 1) | (int + 1) } issue680: (>10 * 2) & 0 issue405: >=100 <= 200 -- out/eval -- permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): ./in.cue:3:5 permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): ./in.cue:3:20 permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): ./in.cue:8:6 permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): ./in.cue:8:18 permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): ./in.cue:12:6 permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): ./in.cue:12:18 issue680: invalid operand >10 ('*' requires concrete value): ./in.cue:15:12 issue405: invalid operand >=100 ('<=' requires concrete value): ./in.cue:17:11 -- out/compile -- permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): ./in.cue:3:5 permanentlyIncompleteOperands.a: invalid operand string ('+' requires concrete value): ./in.cue:3:20 permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): ./in.cue:8:6 permanentlyIncompleteOperandsNested.a: invalid operand int ('+' requires concrete value): ./in.cue:8:18 permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): ./in.cue:12:6 permanentlyIncompleteOperandsDisjunct.a: invalid operand int ('+' requires concrete value): ./in.cue:12:18 issue680: invalid operand >10 ('*' requires concrete value): ./in.cue:15:12 issue405: invalid operand >=100 ('<=' requires concrete value): ./in.cue:17:11 --- in.cue { permanentlyIncompleteOperands: { a: ((string + ":") + string) a: "golang/go:1.13.5" } permanentlyIncompleteOperandsNested: { a: ((int + 1) + (int + 1)) } permanentlyIncompleteOperandsDisjunct: { a: ((int + 1)|(int + 1)) } issue680: ((>10 * 2) & 0) issue405: (>=100 <= 200) } cue-lang-cue-db9cc73/cue/testdata/eval/insertion.txtar000066400000000000000000000144121474664451600231140ustar00rootroot00000000000000# Tests various patterns of insertion of conjuncts. # See https://cuelang.org/issues/2169 -- a.cue -- embeddingDirect: t1: { #a: _ _ } & { #a: "s" #a } embeddingExpr: t1: { #a: _ _ } & { #a: "s" [ #a ][0] } unifiedDirect: { t1: { #a: _ _ } t1: { #a #a: _ } t1: { _ #a: "s" } } unifiedExpr: { t1: { #a: _ _ } t1: { [ #a ][0] #a: _ } t1: { #a: "s" _ } } // These two embeddings both add fields to each other's original source, which // then, in turn, needs to be added. cross: t1: { a: { b: {v: 1, a: w: 2} // from b.a: {x: 2, b: y: 5} } b: { a: {x: 2, b: y: 5} // from a.b: {v: 1, a: v: 2} } a b } -- complex.cue -- // Multiple levels of insertion recursive: t1: { e: {} c: d: e: f: 1 c.d c: d: // This part gets embedded within t1, which ends up adding new fields // to here, when then again need to be embedded in t1, which then // will add more fields to node e. c: d: e: g: 1 } recursive: t2: { c c: c: g: 1 } -- issue2169.cue -- embeddedFunctionalExpr: { #fn: { #in: _ _ } & { #in: "str" ({ #t: _ #t } & { #t: #in _ }) + "" } #fn } -- out/eval/stats -- Leaks: 8 Freed: 59 Reused: 54 Allocs: 13 Retain: 24 Unifications: 67 Conjuncts: 163 Disjuncts: 73 -- out/eval -- (struct){ embeddingDirect: (struct){ t1: (string){ "s" #a: (string){ "s" } } } embeddingExpr: (struct){ t1: (string){ "s" #a: (string){ "s" } } } unifiedDirect: (struct){ t1: (string){ "s" #a: (string){ "s" } } } unifiedExpr: (struct){ t1: (string){ "s" #a: (string){ "s" } } } cross: (struct){ t1: (struct){ a: (struct){ b: (struct){ v: (int){ 1 } a: (struct){ w: (int){ 2 } } y: (int){ 5 } } x: (int){ 2 } w: (int){ 2 } } b: (struct){ a: (struct){ x: (int){ 2 } b: (struct){ y: (int){ 5 } } w: (int){ 2 } } v: (int){ 1 } y: (int){ 5 } } x: (int){ 2 } y: (int){ 5 } v: (int){ 1 } w: (int){ 2 } } } recursive: (struct){ t1: (struct){ e: (struct){ f: (int){ 1 } g: (int){ 1 } } c: (struct){ d: (struct){ e: (struct){ f: (int){ 1 } g: (int){ 1 } } c: (struct){ d: (struct){ e: (struct){ g: (int){ 1 } } } } } } } t2: (struct){ c: (struct){ c: (struct){ g: (int){ 1 } } g: (int){ 1 } } g: (int){ 1 } } } embeddedFunctionalExpr: (string){ "str" #fn: (string){ "str" #in: (string){ "str" } } #in: (string){ "str" } } } -- out/evalalpha -- (struct){ embeddingDirect: (struct){ t1: (string){ "s" #a: (string){ "s" } } } embeddingExpr: (struct){ t1: (string){ "s" #a: (string){ "s" } } } unifiedDirect: (struct){ t1: (string){ "s" #a: (string){ "s" } } } unifiedExpr: (struct){ t1: (string){ "s" #a: (string){ "s" } } } cross: (struct){ t1: (struct){ a: (struct){ b: (struct){ v: (int){ 1 } a: (struct){ w: (int){ 2 } } y: (int){ 5 } } x: (int){ 2 } w: (int){ 2 } } b: (struct){ a: (struct){ x: (int){ 2 } b: (struct){ y: (int){ 5 } } w: (int){ 2 } } v: (int){ 1 } y: (int){ 5 } } v: (int){ 1 } w: (int){ 2 } x: (int){ 2 } y: (int){ 5 } } } recursive: (struct){ t1: (struct){ e: (struct){ f: (int){ 1 } g: (int){ 1 } } c: (struct){ d: (struct){ e: (struct){ f: (int){ 1 } g: (int){ 1 } } c: (struct){ d: (struct){ e: (struct){ g: (int){ 1 } } } } } } } t2: (struct){ c: (struct){ c: (struct){ g: (int){ 1 } } g: (int){ 1 } } g: (int){ 1 } } } embeddedFunctionalExpr: (string){ "str" #fn: (string){ "str" #in: (string){ "str" } } #in: (string){ "str" } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -47,10 +47,10 @@ v: (int){ 1 } y: (int){ 5 } } - x: (int){ 2 } - y: (int){ 5 } v: (int){ 1 } w: (int){ 2 } + x: (int){ 2 } + y: (int){ 5 } } } recursive: (struct){ -- diff/todo/p3 -- Reordering. -- out/compile -- --- a.cue { embeddingDirect: { t1: ({ #a: _ _ } & { #a: "s" 〈0;#a〉 }) } embeddingExpr: { t1: ({ #a: _ _ } & { #a: "s" [ 〈1;#a〉, ][0] }) } unifiedDirect: { t1: { #a: _ _ } t1: { 〈0;#a〉 #a: _ } t1: { _ #a: "s" } } unifiedExpr: { t1: { #a: _ _ } t1: { [ 〈1;#a〉, ][0] #a: _ } t1: { #a: "s" _ } } cross: { t1: { a: { b: { v: 1 a: { w: 2 } } } b: { a: { x: 2 b: { y: 5 } } } 〈0;a〉 〈0;b〉 } } } --- complex.cue { recursive: { t1: { e: {} c: { d: { e: { f: 1 } } } 〈0;c〉.d c: { d: { c: { d: { e: { g: 1 } } } } } } } recursive: { t2: { 〈0;c〉 c: { c: { g: 1 } } } } } --- issue2169.cue { embeddedFunctionalExpr: { #fn: ({ #in: _ _ } & { #in: "str" (({ #t: _ 〈0;#t〉 } & { #t: 〈1;#in〉 _ }) + "") }) 〈0;#fn〉 } } cue-lang-cue-db9cc73/cue/testdata/eval/issue2146.txtar000066400000000000000000000104251474664451600225470ustar00rootroot00000000000000// Issue #2146 // // Ensure that let expressions are uniqued not only per Environment, but also // per arc. This is relevant for disjunctions. Without it, an incorrect // result may be cached for an arbitrary Environment. -- in.cue -- p1: { #A: { x?: int y?: int let list = [x, y] all: [for v in list if v != _|_ {v}] *{ x?: _|_ y: 1 } | _ } a: #A & { x: 3 } b: #A & a } p2: { #A: { x?: int y?: int let list = [x, y] all: [for v in list if v != _|_ {v}] _ | *{ x?: _|_ y: 1 } } a: #A & { x: 3, y: 2 } b: #A & a } -- out/eval/stats -- Leaks: 18 Freed: 171 Reused: 163 Allocs: 26 Retain: 18 Unifications: 173 Conjuncts: 557 Disjuncts: 189 -- out/eval -- (struct){ p1: (struct){ #A: (#struct){ |(*(#struct){ x?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./in.cue:10:8 } y: (int){ 1 } let list#1 = (#list){ 0: (_|_){ // [incomplete] p1.#A.list.0: cannot reference optional field: x: // ./in.cue:6:15 } 1: (int){ 1 } } all: (#list){ 0: (int){ 1 } } }, (#struct){ x?: (int){ int } y?: (int){ int } let list#1 = (#list){ 0: (_|_){ // [incomplete] p1.#A.list.0: cannot reference optional field: x: // ./in.cue:6:15 } 1: (_|_){ // [incomplete] p1.#A.list.1: cannot reference optional field: y: // ./in.cue:6:18 } } all: (#list){ } }) } a: (#struct){ x: (int){ 3 } y?: (int){ int } let list#1 = (#list){ 0: (int){ 3 } 1: (_|_){ // [incomplete] p1.a.list.1: cannot reference optional field: y: // ./in.cue:6:18 } } all: (#list){ 0: (int){ 3 } } } b: (#struct){ x: (int){ 3 } y?: (int){ int } let list#1multi = [ 〈1;x〉, 〈1;y〉, ] all: (#list){ 0: (int){ 3 } } } } p2: (struct){ #A: (#struct){ |(*(#struct){ x?: (_|_){ // [user] explicit error (_|_ literal) in source: // ./in.cue:27:8 } y: (int){ 1 } let list#2 = (#list){ 0: (_|_){ // [incomplete] p2.#A.list.0: cannot reference optional field: x: // ./in.cue:23:15 } 1: (int){ 1 } } all: (#list){ 0: (int){ 1 } } }, (#struct){ x?: (int){ int } y?: (int){ int } let list#2 = (#list){ 0: (_|_){ // [incomplete] p2.#A.list.0: cannot reference optional field: x: // ./in.cue:23:15 } 1: (_|_){ // [incomplete] p2.#A.list.1: cannot reference optional field: y: // ./in.cue:23:18 } } all: (#list){ } }) } a: (#struct){ x: (int){ 3 } y: (int){ 2 } let list#2 = (#list){ 0: (int){ 3 } 1: (int){ 2 } } all: (#list){ 0: (int){ 3 } 1: (int){ 2 } } } b: (#struct){ x: (int){ 3 } y: (int){ 2 } let list#2multi = [ 〈1;x〉, 〈1;y〉, ] all: (#list){ 0: (int){ 3 } 1: (int){ 2 } } } } } -- out/compile -- --- in.cue { p1: { #A: { x?: int y?: int let list#1 = [ 〈1;x〉, 〈1;y〉, ] all: [ for _, v in 〈1;let list#1〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) { 〈1;v〉 }, ] (*{ x?: _|_(explicit error (_|_ literal) in source) y: 1 }|_) } a: (〈0;#A〉 & { x: 3 }) b: (〈0;#A〉 & 〈0;a〉) } p2: { #A: { x?: int y?: int let list#2 = [ 〈1;x〉, 〈1;y〉, ] all: [ for _, v in 〈1;let list#2〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) { 〈1;v〉 }, ] (_|*{ x?: _|_(explicit error (_|_ literal) in source) y: 1 }) } a: (〈0;#A〉 & { x: 3 y: 2 }) b: (〈0;#A〉 & 〈0;a〉) } } cue-lang-cue-db9cc73/cue/testdata/eval/issue2235.txtar000066400000000000000000000416131474664451600225510ustar00rootroot00000000000000// Test various orders // https://cuelang.org/issues/2235 -- reductions.cue -- // Each of these tests triggers a slightly different path. t1: { params: x.y x: y: {} for _ in x { if true { x: y: a: {} } } } t2: { out: X.y let X = m.x m: x: y: {} for v in m { if true { m: x: y: z: {} } } } t3: { out: foo.bar foo: bar: {} for _ in foo { for name, _ in foo { foo: (name): _ } } } -- issue2235.cue -- package kubecluster import ( "strings" "net" ) shorewallParams: close({ [=~"^[A-Z0-9_]+$"]: [...net.IP] }) #Cluster: { clusterName: string shorewallPrefix: "KUBERNETES_\(strings.ToUpper(clusterName))" } clusters: [CLUSTER=string]: #Cluster & { clusterName: CLUSTER } #Cluster: { globalIngressControllers: [string]: #GlobalIngressController globalIngressControllers: admin: #GlobalIngressController & { class: "admin" } for _, c in globalIngressControllers { objects: c.objects } } for clusterName, cluster in clusters { for class, controller in cluster.globalIngressControllers { let svc = controller.objects.namespaced.ingress.Service["\(class)-nginx-ingress-controller"] shorewallParams: "\(cluster.shorewallPrefix)_INGRESS_\(strings.ToUpper(class))": svc.spec.externalIPs } } #GlobalIngressController: { class: string objects: namespaced: ingress: { Service: "\(class)-nginx-ingress-controller": { spec: { externalIPs: ["127.0.0.1"] } } } for kind, objs in objects.namespaced.ingress { for name, obj in objs { objects: namespaced: ingress: "\(kind)": "\(name)": metadata: labels: { "ingress-class": class stack: "ingress" ... } } } } clusters: foo: {} -- out/eval/stats -- Leaks: 3 Freed: 101 Reused: 84 Allocs: 20 Retain: 72 Unifications: 104 Conjuncts: 271 Disjuncts: 161 -- out/evalalpha -- (struct){ shorewallParams: (#struct){ KUBERNETES_FOO_INGRESS_ADMIN: (#list){ 0: (string){ "127.0.0.1" } } } #Cluster: (#struct){ clusterName: (string){ string } shorewallPrefix: (_|_){ // [incomplete] #Cluster.shorewallPrefix: invalid interpolation: error in call to strings.ToUpper: non-concrete value string: // ./issue2235.cue:14:19 // ./issue2235.cue:13:19 // ./issue2235.cue:14:33 } globalIngressControllers: (#struct){ admin: (#struct){ class: (string){ "admin" } objects: (#struct){ namespaced: (#struct){ ingress: (#struct){ Service: (#struct){ "admin-nginx-ingress-controller": (#struct){ spec: (#struct){ externalIPs: (#list){ 0: (string){ "127.0.0.1" } } } metadata: (#struct){ labels: (#struct){ "ingress-class": (string){ "admin" } stack: (string){ "ingress" } } } } } } } } } } objects: ~(#Cluster.globalIngressControllers.admin.objects) } clusters: (struct){ foo: (#struct){ clusterName: (string){ "foo" } shorewallPrefix: (string){ "KUBERNETES_FOO" } globalIngressControllers: (#struct){ admin: (#struct){ class: (string){ "admin" } objects: (#struct){ namespaced: (#struct){ ingress: (#struct){ Service: (#struct){ "admin-nginx-ingress-controller": (#struct){ spec: (#struct){ externalIPs: (#list){ 0: (string){ "127.0.0.1" } } } metadata: (#struct){ labels: (#struct){ "ingress-class": (string){ "admin" } stack: (string){ "ingress" } } } } } } } } } } objects: ~(clusters.foo.globalIngressControllers.admin.objects) } } #GlobalIngressController: (_|_){ // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: key value of dynamic field must be concrete, found _|_(invalid interpolation: #GlobalIngressController.objects.namespaced.ingress.Service: non-concrete value string (type string)): // ./issue2235.cue:43:12 class: (string){ string } objects: (#struct){ namespaced: (#struct){ ingress: (_|_){ // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: key value of dynamic field must be concrete, found _|_(invalid interpolation: #GlobalIngressController.objects.namespaced.ingress.Service: non-concrete value string (type string)): // ./issue2235.cue:43:12 Service: (_|_){ // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: key value of dynamic field must be concrete, found _|_(invalid interpolation: #GlobalIngressController.objects.namespaced.ingress.Service: non-concrete value string (type string)): // ./issue2235.cue:43:12 } } } } } t1: (struct){ params: ~(t1.x.y) x: (struct){ y: (struct){ a: (struct){ } } } } t2: (struct){ out: ~(t2.m.x.y) let X#2 = ~(t2.m.x) m: (struct){ x: (struct){ y: (struct){ z: (struct){ } } } } } t3: (struct){ out: (struct){ } foo: (struct){ bar: (struct){ } } } let svc#1multi = 〈1;controller〉.objects.namespaced.ingress.Service["\(〈1;class〉)-nginx-ingress-controller"] } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -38,27 +38,7 @@ } } } - objects: (#struct){ - namespaced: (#struct){ - ingress: (#struct){ - Service: (#struct){ - "admin-nginx-ingress-controller": (#struct){ - spec: (#struct){ - externalIPs: (#list){ - 0: (string){ "127.0.0.1" } - } - } - metadata: (#struct){ - labels: (#struct){ - "ingress-class": (string){ "admin" } - stack: (string){ "ingress" } - } - } - } - } - } - } - } + objects: ~(#Cluster.globalIngressControllers.admin.objects) } clusters: (struct){ foo: (#struct){ @@ -90,44 +70,21 @@ } } } - objects: (#struct){ - namespaced: (#struct){ - ingress: (#struct){ - Service: (#struct){ - "admin-nginx-ingress-controller": (#struct){ - spec: (#struct){ - externalIPs: (#list){ - 0: (string){ "127.0.0.1" } - } - } - metadata: (#struct){ - labels: (#struct){ - "ingress-class": (string){ "admin" } - stack: (string){ "ingress" } - } - } - } - } - } - } - } + objects: ~(clusters.foo.globalIngressControllers.admin.objects) } } #GlobalIngressController: (_|_){ - // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: invalid interpolation: non-concrete value string (type string): + // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: key value of dynamic field must be concrete, found _|_(invalid interpolation: #GlobalIngressController.objects.namespaced.ingress.Service: non-concrete value string (type string)): // ./issue2235.cue:43:12 - // ./issue2235.cue:40:9 class: (string){ string } objects: (#struct){ namespaced: (#struct){ ingress: (_|_){ - // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: invalid interpolation: non-concrete value string (type string): + // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: key value of dynamic field must be concrete, found _|_(invalid interpolation: #GlobalIngressController.objects.namespaced.ingress.Service: non-concrete value string (type string)): // ./issue2235.cue:43:12 - // ./issue2235.cue:40:9 Service: (_|_){ - // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: invalid interpolation: non-concrete value string (type string): + // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: key value of dynamic field must be concrete, found _|_(invalid interpolation: #GlobalIngressController.objects.namespaced.ingress.Service: non-concrete value string (type string)): // ./issue2235.cue:43:12 - // ./issue2235.cue:40:9 } } } @@ -134,10 +91,7 @@ } } t1: (struct){ - params: (struct){ - a: (struct){ - } - } + params: ~(t1.x.y) x: (struct){ y: (struct){ a: (struct){ @@ -146,16 +100,8 @@ } } t2: (struct){ - out: (struct){ - z: (struct){ - } - } - let X#2 = (struct){ - y: (struct){ - z: (struct){ - } - } - } + out: ~(t2.m.x.y) + let X#2 = ~(t2.m.x) m: (struct){ x: (struct){ y: (struct){ -- diff/todo/p2 -- Different, but okay, error message, but missing some positions -- out/eval -- (struct){ shorewallParams: (#struct){ KUBERNETES_FOO_INGRESS_ADMIN: (#list){ 0: (string){ "127.0.0.1" } } } #Cluster: (#struct){ clusterName: (string){ string } shorewallPrefix: (_|_){ // [incomplete] #Cluster.shorewallPrefix: invalid interpolation: error in call to strings.ToUpper: non-concrete value string: // ./issue2235.cue:14:19 // ./issue2235.cue:13:19 // ./issue2235.cue:14:33 } globalIngressControllers: (#struct){ admin: (#struct){ class: (string){ "admin" } objects: (#struct){ namespaced: (#struct){ ingress: (#struct){ Service: (#struct){ "admin-nginx-ingress-controller": (#struct){ spec: (#struct){ externalIPs: (#list){ 0: (string){ "127.0.0.1" } } } metadata: (#struct){ labels: (#struct){ "ingress-class": (string){ "admin" } stack: (string){ "ingress" } } } } } } } } } } objects: (#struct){ namespaced: (#struct){ ingress: (#struct){ Service: (#struct){ "admin-nginx-ingress-controller": (#struct){ spec: (#struct){ externalIPs: (#list){ 0: (string){ "127.0.0.1" } } } metadata: (#struct){ labels: (#struct){ "ingress-class": (string){ "admin" } stack: (string){ "ingress" } } } } } } } } } clusters: (struct){ foo: (#struct){ clusterName: (string){ "foo" } shorewallPrefix: (string){ "KUBERNETES_FOO" } globalIngressControllers: (#struct){ admin: (#struct){ class: (string){ "admin" } objects: (#struct){ namespaced: (#struct){ ingress: (#struct){ Service: (#struct){ "admin-nginx-ingress-controller": (#struct){ spec: (#struct){ externalIPs: (#list){ 0: (string){ "127.0.0.1" } } } metadata: (#struct){ labels: (#struct){ "ingress-class": (string){ "admin" } stack: (string){ "ingress" } } } } } } } } } } objects: (#struct){ namespaced: (#struct){ ingress: (#struct){ Service: (#struct){ "admin-nginx-ingress-controller": (#struct){ spec: (#struct){ externalIPs: (#list){ 0: (string){ "127.0.0.1" } } } metadata: (#struct){ labels: (#struct){ "ingress-class": (string){ "admin" } stack: (string){ "ingress" } } } } } } } } } } #GlobalIngressController: (_|_){ // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: invalid interpolation: non-concrete value string (type string): // ./issue2235.cue:43:12 // ./issue2235.cue:40:9 class: (string){ string } objects: (#struct){ namespaced: (#struct){ ingress: (_|_){ // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: invalid interpolation: non-concrete value string (type string): // ./issue2235.cue:43:12 // ./issue2235.cue:40:9 Service: (_|_){ // [incomplete] #GlobalIngressController.objects.namespaced.ingress.Service: invalid interpolation: non-concrete value string (type string): // ./issue2235.cue:43:12 // ./issue2235.cue:40:9 } } } } } t1: (struct){ params: (struct){ a: (struct){ } } x: (struct){ y: (struct){ a: (struct){ } } } } t2: (struct){ out: (struct){ z: (struct){ } } let X#2 = (struct){ y: (struct){ z: (struct){ } } } m: (struct){ x: (struct){ y: (struct){ z: (struct){ } } } } } t3: (struct){ out: (struct){ } foo: (struct){ bar: (struct){ } } } let svc#1multi = 〈1;controller〉.objects.namespaced.ingress.Service["\(〈1;class〉)-nginx-ingress-controller"] } -- out/compile -- --- issue2235.cue { shorewallParams: close({ [=~"^[A-Z0-9_]+$"]: [ ...〈import;net〉.IP, ] }) #Cluster: { clusterName: string shorewallPrefix: "KUBERNETES_\(〈import;strings〉.ToUpper(〈0;clusterName〉))" } clusters: { [string]: (〈1;#Cluster〉 & { clusterName: 〈1;-〉 }) } #Cluster: { globalIngressControllers: { [string]: 〈2;#GlobalIngressController〉 } globalIngressControllers: { admin: (〈2;#GlobalIngressController〉 & { class: "admin" }) } for _, c in 〈0;globalIngressControllers〉 { objects: 〈1;c〉.objects } } for clusterName, cluster in 〈0;clusters〉 { for class, controller in 〈1;cluster〉.globalIngressControllers { let svc#1multi = 〈1;controller〉.objects.namespaced.ingress.Service["\(〈1;class〉)-nginx-ingress-controller"] shorewallParams: { "\(〈4;cluster〉.shorewallPrefix)_INGRESS_\(〈import;strings〉.ToUpper(〈2;class〉))": 〈1;let svc#1〉.spec.externalIPs } } } #GlobalIngressController: { class: string objects: { namespaced: { ingress: { Service: { "\(〈4;class〉)-nginx-ingress-controller": { spec: { externalIPs: [ "127.0.0.1", ] } } } } } } for kind, objs in 〈0;objects〉.namespaced.ingress { for name, obj in 〈1;objs〉 { objects: { namespaced: { ingress: { "\(〈6;kind〉)": { "\(〈5;name〉)": { metadata: { labels: { "ingress-class": 〈11;class〉 stack: "ingress" ... } } } } } } } } } } clusters: { foo: {} } } --- reductions.cue { t1: { params: 〈0;x〉.y x: { y: {} } for _, _ in 〈0;x〉 { if true { x: { y: { a: {} } } } } } t2: { out: 〈0;let X#2〉.y let X#2 = 〈0;m〉.x m: { x: { y: {} } } for _, v in 〈0;m〉 { if true { m: { x: { y: { z: {} } } } } } } t3: { out: 〈0;foo〉.bar foo: { bar: {} } for _, _ in 〈0;foo〉 { for name, _ in 〈2;foo〉 { foo: { 〈2;name〉: _ } } } } } cue-lang-cue-db9cc73/cue/testdata/eval/issue2550.txtar000066400000000000000000000024671474664451600225550ustar00rootroot00000000000000-- in.cue -- foo: string bar: close({}) if bar.missing == "x" { let _bar = bar foo: _bar } -- out/compile -- --- in.cue { foo: string bar: close({}) if (〈0;bar〉.missing == "x") { let _bar#1 = 〈1;bar〉 foo: 〈0;let _bar#1〉 } } -- out/eval/stats -- Leaks: 1 Freed: 4 Reused: 1 Allocs: 4 Retain: 2 Unifications: 5 Conjuncts: 5 Disjuncts: 6 -- out/eval -- Errors: undefined field: missing: ./in.cue:4:8 Result: (_|_){ // [eval] undefined field: missing: // ./in.cue:4:8 foo: (string){ string } bar: (#struct){ } let _bar#1 = (_){ _ } } -- out/evalalpha -- Errors: undefined field: missing: ./in.cue:4:8 Result: (_|_){ // [eval] undefined field: missing: // ./in.cue:4:8 foo: (_|_){ // [incomplete] undefined field: missing: // ./in.cue:4:8 } bar: (#struct){ } let _bar#1multi = 〈1;bar〉 } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -6,8 +6,11 @@ (_|_){ // [eval] undefined field: missing: // ./in.cue:4:8 - foo: (string){ string } + foo: (_|_){ + // [incomplete] undefined field: missing: + // ./in.cue:4:8 + } bar: (#struct){ } - let _bar#1 = (_){ _ } + let _bar#1multi = 〈1;bar〉 } -- diff/todo/p2 -- Let seems to have misplaced error, even though it does not affect outcome. cue-lang-cue-db9cc73/cue/testdata/eval/issue2649.txtar000066400000000000000000000003541474664451600225570ustar00rootroot00000000000000-- in.cue -- (4 + 8 + 12) / 3 -- out/compile -- --- in.cue { (((4 + 8) + 12) / 3) } -- out/eval/stats -- Leaks: 0 Freed: 1 Reused: 0 Allocs: 1 Retain: 0 Unifications: 1 Conjuncts: 2 Disjuncts: 1 -- out/eval -- (float){ 8.0 } cue-lang-cue-db9cc73/cue/testdata/eval/issue285.txtar000066400000000000000000000026771474664451600225030ustar00rootroot00000000000000-- in.cue -- #TopLevel: [name=string]: { path: string content: string } #Mid: #TopLevel & { myoutput: path: "/output" } val: #Mid & {} & {myoutput: {content: "foo"}} // Should work. -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 6 Allocs: 4 Retain: 0 Unifications: 10 Conjuncts: 23 Disjuncts: 10 -- out/evalalpha -- (struct){ #TopLevel: (#struct){ } #Mid: (#struct){ myoutput: (#struct){ path: (string){ "/output" } content: (string){ string } } } val: (#struct){ myoutput: (#struct){ content: (string){ "foo" } path: (string){ "/output" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -9,8 +9,8 @@ } val: (#struct){ myoutput: (#struct){ - path: (string){ "/output" } content: (string){ "foo" } + path: (string){ "/output" } } } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ #TopLevel: (#struct){ } #Mid: (#struct){ myoutput: (#struct){ path: (string){ "/output" } content: (string){ string } } } val: (#struct){ myoutput: (#struct){ path: (string){ "/output" } content: (string){ "foo" } } } } -- out/compile -- --- in.cue { #TopLevel: { [string]: { path: string content: string } } #Mid: (〈0;#TopLevel〉 & { myoutput: { path: "/output" } }) val: ((〈0;#Mid〉 & {}) & { myoutput: { content: "foo" } }) } cue-lang-cue-db9cc73/cue/testdata/eval/issue295.txtar000066400000000000000000000005001474664451600224630ustar00rootroot00000000000000-- in.cue -- p: close({ "\("f")": _ }) p: f: 9 -- out/compile -- --- in.cue { p: close({ "\("f")": _ }) p: { f: 9 } } -- out/eval/stats -- Leaks: 1 Freed: 3 Reused: 0 Allocs: 4 Retain: 1 Unifications: 4 Conjuncts: 7 Disjuncts: 4 -- out/eval -- (struct){ p: (#struct){ f: (int){ 9 } } } cue-lang-cue-db9cc73/cue/testdata/eval/issue3301.txtar000066400000000000000000000017451474664451600225460ustar00rootroot00000000000000-- in.cue -- object: #Leaf & {} #Base: { extra?: {...} } #Mid: { #Base } #Leaf: { #Mid extra?: {...} more?: int if extra.foo != _|_ { if more != _|_ { foo: "bar" } } } -- out/eval -- (struct){ object: (#struct){ extra?: (#struct){ } more?: (int){ int } } #Base: (#struct){ extra?: (#struct){ } } #Mid: (#struct){ extra?: (#struct){ } } #Leaf: (#struct){ extra?: (#struct){ } more?: (int){ int } } } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 5 Allocs: 6 Retain: 7 Unifications: 11 Conjuncts: 25 Disjuncts: 18 -- out/compile -- --- in.cue { object: (〈0;#Leaf〉 & {}) #Base: { extra?: { ... } } #Mid: { 〈1;#Base〉 } #Leaf: { 〈1;#Mid〉 extra?: { ... } more?: int if (〈0;extra〉.foo != _|_(explicit error (_|_ literal) in source)) { if (〈1;more〉 != _|_(explicit error (_|_ literal) in source)) { foo: "bar" } } } } cue-lang-cue-db9cc73/cue/testdata/eval/issue3330.txtar000066400000000000000000000161001474664451600225370ustar00rootroot00000000000000-- in.cue -- import "list" issue3330: { #A: { let empty = {} // Reference to empty is within the definition that defines it. Closedness // thus does not trigger. field: null | { n: int } field: empty & { n: 3 } } out: list.Concat([[#A]]) } eliminated: { // This test case ensures a definition is only used for the empty struct. // This ensures that the elimination of disjuncts is triggered, ensuring // the code path that caused the panic in issue3330 is triggered even when // the closedness bug that triggered it indirectly is fixed. #empty: {} x: null | { n: 3 } x: #empty & { n: 3 } out: len(x) } simplified: { // This is a different take on the above bug that demonstrates the issue // is only triggered after a definition is referenced. #struct: { field: { n: 3 } & g g: {} } out: #struct & {} } -- out/eval/stats -- Leaks: 0 Freed: 43 Reused: 34 Allocs: 9 Retain: 3 Unifications: 35 Conjuncts: 69 Disjuncts: 46 -- out/evalalpha -- Errors: eliminated.x: 2 errors in empty disjunction: eliminated.x: conflicting values null and {} (mismatched types null and struct): ./in.cue:21:10 ./in.cue:22:5 eliminated.x.n: field not allowed: ./in.cue:23:5 ./in.cue:23:16 Result: (_|_){ // [eval] issue3330: (struct){ #A: (#struct){ let empty#1 = (#struct){ } field: (#struct){ n: (int){ 3 } } } out: (#list){ 0: ~(issue3330.#A) } } eliminated: (_|_){ // [eval] #empty: (#struct){ } x: (_|_){ // [eval] eliminated.x: 2 errors in empty disjunction: // eliminated.x: conflicting values null and {} (mismatched types null and struct): // ./in.cue:21:10 // ./in.cue:22:5 // eliminated.x.n: field not allowed: // ./in.cue:23:5 // ./in.cue:23:16 n: (_|_){ // [eval] eliminated.x.n: field not allowed: // ./in.cue:23:5 // ./in.cue:23:16 } } out: (_|_){ // [eval] eliminated.x: 2 errors in empty disjunction: // eliminated.x: conflicting values null and {} (mismatched types null and struct): // ./in.cue:21:10 // ./in.cue:22:5 // eliminated.x.n: field not allowed: // ./in.cue:23:5 // ./in.cue:23:16 } } simplified: (struct){ #struct: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,11 +1,9 @@ Errors: eliminated.x: 2 errors in empty disjunction: -eliminated.x: conflicting values null and {n:3} (mismatched types null and struct): +eliminated.x: conflicting values null and {} (mismatched types null and struct): + ./in.cue:21:10 ./in.cue:22:5 - ./in.cue:23:14 eliminated.x.n: field not allowed: - ./in.cue:21:10 - ./in.cue:22:14 ./in.cue:23:5 ./in.cue:23:16 @@ -21,13 +19,7 @@ } } out: (#list){ - 0: (#struct){ - let empty#1 = (#struct){ - } - field: (#struct){ - n: (int){ 3 } - } - } + 0: ~(issue3330.#A) } } eliminated: (_|_){ @@ -36,18 +28,14 @@ } x: (_|_){ // [eval] eliminated.x: 2 errors in empty disjunction: - // eliminated.x: conflicting values null and {n:3} (mismatched types null and struct): - // ./in.cue:22:5 - // ./in.cue:23:14 - // eliminated.x.n: field not allowed: - // ./in.cue:21:10 - // ./in.cue:22:14 + // eliminated.x: conflicting values null and {} (mismatched types null and struct): + // ./in.cue:21:10 + // ./in.cue:22:5 + // eliminated.x.n: field not allowed: // ./in.cue:23:5 // ./in.cue:23:16 n: (_|_){ // [eval] eliminated.x.n: field not allowed: - // ./in.cue:21:10 - // ./in.cue:22:14 // ./in.cue:23:5 // ./in.cue:23:16 } @@ -54,12 +42,10 @@ } out: (_|_){ // [eval] eliminated.x: 2 errors in empty disjunction: - // eliminated.x: conflicting values null and {n:3} (mismatched types null and struct): - // ./in.cue:22:5 - // ./in.cue:23:14 - // eliminated.x.n: field not allowed: - // ./in.cue:21:10 - // ./in.cue:22:14 + // eliminated.x: conflicting values null and {} (mismatched types null and struct): + // ./in.cue:21:10 + // ./in.cue:22:5 + // eliminated.x.n: field not allowed: // ./in.cue:23:5 // ./in.cue:23:16 } -- diff/todo/p3 -- Small differences in error output. -- out/eval -- Errors: eliminated.x: 2 errors in empty disjunction: eliminated.x: conflicting values null and {n:3} (mismatched types null and struct): ./in.cue:22:5 ./in.cue:23:14 eliminated.x.n: field not allowed: ./in.cue:21:10 ./in.cue:22:14 ./in.cue:23:5 ./in.cue:23:16 Result: (_|_){ // [eval] issue3330: (struct){ #A: (#struct){ let empty#1 = (#struct){ } field: (#struct){ n: (int){ 3 } } } out: (#list){ 0: (#struct){ let empty#1 = (#struct){ } field: (#struct){ n: (int){ 3 } } } } } eliminated: (_|_){ // [eval] #empty: (#struct){ } x: (_|_){ // [eval] eliminated.x: 2 errors in empty disjunction: // eliminated.x: conflicting values null and {n:3} (mismatched types null and struct): // ./in.cue:22:5 // ./in.cue:23:14 // eliminated.x.n: field not allowed: // ./in.cue:21:10 // ./in.cue:22:14 // ./in.cue:23:5 // ./in.cue:23:16 n: (_|_){ // [eval] eliminated.x.n: field not allowed: // ./in.cue:21:10 // ./in.cue:22:14 // ./in.cue:23:5 // ./in.cue:23:16 } } out: (_|_){ // [eval] eliminated.x: 2 errors in empty disjunction: // eliminated.x: conflicting values null and {n:3} (mismatched types null and struct): // ./in.cue:22:5 // ./in.cue:23:14 // eliminated.x.n: field not allowed: // ./in.cue:21:10 // ./in.cue:22:14 // ./in.cue:23:5 // ./in.cue:23:16 } } simplified: (struct){ #struct: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } out: (#struct){ field: (#struct){ n: (int){ 3 } } g: (#struct){ } } } } -- out/compile -- --- in.cue { issue3330: { #A: { let empty#1 = {} field: (null|{ n: int }) field: (〈0;let empty#1〉 & { n: 3 }) } out: 〈import;list〉.Concat([ [ 〈2;#A〉, ], ]) } eliminated: { #empty: {} x: (null|{ n: 3 }) x: (〈0;#empty〉 & { n: 3 }) out: len(〈0;x〉) } simplified: { #struct: { field: ({ n: 3 } & 〈0;g〉) g: {} } out: (〈0;#struct〉 & {}) } } cue-lang-cue-db9cc73/cue/testdata/eval/issue349.txtar000066400000000000000000000013111474664451600224640ustar00rootroot00000000000000-- in.cue -- ex: { "aaa": "aaa" "list": "list" "zzz": "zzz" "AAA": "AAA" "html": "html" "HTML": "html" "ZZZ": "ZZZ" "Html": "html" } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 7 Allocs: 3 Retain: 0 Unifications: 10 Conjuncts: 10 Disjuncts: 10 -- out/eval -- (struct){ ex: (struct){ aaa: (string){ "aaa" } list: (string){ "list" } zzz: (string){ "zzz" } AAA: (string){ "AAA" } html: (string){ "html" } HTML: (string){ "html" } ZZZ: (string){ "ZZZ" } Html: (string){ "html" } } } -- out/compile -- --- in.cue { ex: { aaa: "aaa" list: "list" zzz: "zzz" AAA: "AAA" html: "html" HTML: "html" ZZZ: "ZZZ" Html: "html" } } cue-lang-cue-db9cc73/cue/testdata/eval/issue353.txtar000066400000000000000000000015061474664451600224650ustar00rootroot00000000000000-- in.cue -- e: #Example e: a: "hello" #Example: { a: string { value?: string } | { externalValue?: string } } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 9 Allocs: 6 Retain: 0 Unifications: 11 Conjuncts: 21 Disjuncts: 15 -- out/eval -- (struct){ e: (#struct){ |((#struct){ a: (string){ "hello" } value?: (string){ string } }, (#struct){ a: (string){ "hello" } externalValue?: (string){ string } }) } #Example: (#struct){ |((#struct){ a: (string){ string } value?: (string){ string } }, (#struct){ a: (string){ string } externalValue?: (string){ string } }) } } -- out/compile -- --- in.cue { e: 〈0;#Example〉 e: { a: "hello" } #Example: { a: string ({ value?: string }|{ externalValue?: string }) } } cue-lang-cue-db9cc73/cue/testdata/eval/issue494.txtar000066400000000000000000000044251474664451600224760ustar00rootroot00000000000000-- in.cue -- _Q: [{pos: 0}, {pos: 1}] a: [rn=string]: _Q[0:len(a[rn])] a: ben: [{}] b: [rn=string]: _Q[0:1] b: ben: [{}] c: [rn=string]: [...{l: len(a[rn])}] c: ben: [{}] #d: [rn=string]: [...{pos: uint}] & _Q[0:len(#d[rn])] #d: ben: [{}] d: #d -- out/eval/stats -- Leaks: 0 Freed: 26 Reused: 21 Allocs: 5 Retain: 0 Unifications: 26 Conjuncts: 56 Disjuncts: 28 -- out/evalalpha -- (struct){ _Q: (#list){ 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } a: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } b: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } c: (struct){ ben: (#list){ 0: (struct){ l: (int){ 1 } } } } #d: (#struct){ ben: (#list){ 0: (#struct){ pos: (int){ 0 } } } } d: ~(#d) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -35,11 +35,5 @@ } } } - d: (#struct){ - ben: (#list){ - 0: (#struct){ - pos: (int){ 0 } - } - } - } + d: ~(#d) } -- out/eval -- (struct){ _Q: (#list){ 0: (struct){ pos: (int){ 0 } } 1: (struct){ pos: (int){ 1 } } } a: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } b: (struct){ ben: (#list){ 0: (struct){ pos: (int){ 0 } } } } c: (struct){ ben: (#list){ 0: (struct){ l: (int){ 1 } } } } #d: (#struct){ ben: (#list){ 0: (#struct){ pos: (int){ 0 } } } } d: (#struct){ ben: (#list){ 0: (#struct){ pos: (int){ 0 } } } } } -- out/compile -- --- in.cue { _Q: [ { pos: 0 }, { pos: 1 }, ] a: { [string]: 〈1;_Q〉[0:len(〈1;a〉[〈0;-〉])] } a: { ben: [ {}, ] } b: { [string]: 〈1;_Q〉[0:1] } b: { ben: [ {}, ] } c: { [string]: [ ...{ l: len(〈3;a〉[〈2;-〉]) }, ] } c: { ben: [ {}, ] } #d: { [string]: ([ ...{ pos: &(int, >=0) }, ] & 〈1;_Q〉[0:len(〈1;#d〉[〈0;-〉])]) } #d: { ben: [ {}, ] } d: 〈0;#d〉 } cue-lang-cue-db9cc73/cue/testdata/eval/issue500.txtar000066400000000000000000000032021474664451600224520ustar00rootroot00000000000000-- in.cue -- package x import "strings" import "list" a: strings.Join(strings.Split("test", "")[1:], "") b: strings.Join(["t", "e", "s", "t"][1:], "") c: ["t", "e", "s", "t"][1:] d: strings.Join(c, "") e: strings.Join(list.Concat([["a"], ["b"]]), "") f: list.Concat([["a"], ["b"]]) g: strings.Join(f, "") h: strings.Join(list.Repeat(["a"], 3), "") i: list.Repeat(["b"], 3) j: strings.Join(i, "") -- out/eval/stats -- Leaks: 2 Freed: 36 Reused: 31 Allocs: 7 Retain: 6 Unifications: 38 Conjuncts: 45 Disjuncts: 42 -- out/eval -- (struct){ a: (string){ "est" } b: (string){ "est" } c: (#list){ 0: (string){ "e" } 1: (string){ "s" } 2: (string){ "t" } } d: (string){ "est" } e: (string){ "ab" } f: (#list){ 0: (string){ "a" } 1: (string){ "b" } } g: (string){ "ab" } h: (string){ "aaa" } i: (#list){ 0: (string){ "b" } 1: (string){ "b" } 2: (string){ "b" } } j: (string){ "bbb" } } -- out/compile -- --- in.cue { a: 〈import;strings〉.Join(〈import;strings〉.Split("test", "")[1:], "") b: 〈import;strings〉.Join([ "t", "e", "s", "t", ][1:], "") c: [ "t", "e", "s", "t", ][1:] d: 〈import;strings〉.Join(〈0;c〉, "") e: 〈import;strings〉.Join(〈import;list〉.Concat([ [ "a", ], [ "b", ], ]), "") f: 〈import;list〉.Concat([ [ "a", ], [ "b", ], ]) g: 〈import;strings〉.Join(〈0;f〉, "") h: 〈import;strings〉.Join(〈import;list〉.Repeat([ "a", ], 3), "") i: 〈import;list〉.Repeat([ "b", ], 3) j: 〈import;strings〉.Join(〈0;i〉, "") } cue-lang-cue-db9cc73/cue/testdata/eval/issue545.txtar000066400000000000000000000104721474664451600224720ustar00rootroot00000000000000title: Simplification of validators. -- in.cue -- package main import ( "strings" "time" ) t1: { #Test: { #HTTP: =~"^http://" #SSH: !~"^ssh://" #USER: strings.MinRunes(3) source: #HTTP | #SSH | #USER | #Test } foo: #Test & { source: "http://blablabla" } bar: #Test & { source: foo } } t2: { str: "foo" a: =~str b: =~"foo" c: a & b & a & b d: time.Time e: time.Time() f: d & e & d & e } -- out/eval/stats -- Leaks: 0 Freed: 121 Reused: 107 Allocs: 14 Retain: 0 Unifications: 65 Conjuncts: 205 Disjuncts: 121 -- out/evalalpha -- (struct){ t1: (struct){ #Test: (#struct){ #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } source: (string){ |((string){ =~"^http://" }, (string){ !~"^ssh://" }, (string){ strings.MinRunes(3) }) } } foo: (#struct){ source: (string){ "http://blablabla" } #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } } bar: (#struct){ source: (#struct){ source: (string){ "http://blablabla" } #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } } #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } } } t2: (struct){ str: (string){ "foo" } a: (string){ =~"foo" } b: (string){ =~"foo" } c: (string){ =~"foo" } d: (string){ time.Time() } e: (string){ time.Time() } f: (string){ time.Time() } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -7,21 +7,21 @@ source: (string){ |((string){ =~"^http://" }, (string){ !~"^ssh://" }, (string){ strings.MinRunes(3) }) } } foo: (#struct){ - #HTTP: (string){ =~"^http://" } - #SSH: (string){ !~"^ssh://" } - #USER: (string){ strings.MinRunes(3) } source: (string){ "http://blablabla" } + #HTTP: (string){ =~"^http://" } + #SSH: (string){ !~"^ssh://" } + #USER: (string){ strings.MinRunes(3) } } bar: (#struct){ - #HTTP: (string){ =~"^http://" } - #SSH: (string){ !~"^ssh://" } - #USER: (string){ strings.MinRunes(3) } source: (#struct){ + source: (string){ "http://blablabla" } #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } - source: (string){ "http://blablabla" } } + #HTTP: (string){ =~"^http://" } + #SSH: (string){ !~"^ssh://" } + #USER: (string){ strings.MinRunes(3) } } } t2: (struct){ -- diff/todo/p3 -- Reordering. -- out/eval -- (struct){ t1: (struct){ #Test: (#struct){ #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } source: (string){ |((string){ =~"^http://" }, (string){ !~"^ssh://" }, (string){ strings.MinRunes(3) }) } } foo: (#struct){ #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } source: (string){ "http://blablabla" } } bar: (#struct){ #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } source: (#struct){ #HTTP: (string){ =~"^http://" } #SSH: (string){ !~"^ssh://" } #USER: (string){ strings.MinRunes(3) } source: (string){ "http://blablabla" } } } } t2: (struct){ str: (string){ "foo" } a: (string){ =~"foo" } b: (string){ =~"foo" } c: (string){ =~"foo" } d: (string){ time.Time() } e: (string){ time.Time() } f: (string){ time.Time() } } } -- out/compile -- --- in.cue { t1: { #Test: { #HTTP: =~"^http://" #SSH: !~"^ssh://" #USER: 〈import;strings〉.MinRunes(3) source: (〈0;#HTTP〉|〈0;#SSH〉|〈0;#USER〉|〈1;#Test〉) } foo: (〈0;#Test〉 & { source: "http://blablabla" }) bar: (〈0;#Test〉 & { source: 〈1;foo〉 }) } t2: { str: "foo" a: =~〈0;str〉 b: =~"foo" c: (((〈0;a〉 & 〈0;b〉) & 〈0;a〉) & 〈0;b〉) d: 〈import;time〉.Time e: 〈import;time〉.Time() f: (((〈0;d〉 & 〈0;e〉) & 〈0;d〉) & 〈0;e〉) } } cue-lang-cue-db9cc73/cue/testdata/eval/issue599.txtar000066400000000000000000000134261474664451600225050ustar00rootroot00000000000000-- in.cue -- package deps a: { #A: { n: string depends_on: [...#AnyA] } #AnyA: { n: string depends_on: [...#AnyA] ... } #A1: { #A x: int y: z: string // Comment to avoid error } #A2: { #A i: string } s: [Name=string]: #AnyA & {n: Name} s: foo: #A1 & { x: 10 y: z: "z" // Comment to avoid error } s: bar: #A2 & { i: "hello bar" depends_on: [s.foo] } } b: { #A: { f: {...} } #A1: { #A // f: {...} // Uncomment to fix } #C: { d: {...} } s: [string]: #A1 s: foo: { f: #C & { d: foo: "bar" } } } -- out/eval/stats -- Leaks: 0 Freed: 47 Reused: 39 Allocs: 8 Retain: 0 Unifications: 47 Conjuncts: 122 Disjuncts: 47 -- out/evalalpha -- (struct){ a: (struct){ #A: (#struct){ n: (string){ string } depends_on: (list){ } } #AnyA: (#struct){ n: (string){ string } depends_on: (list){ } } #A1: (#struct){ x: (int){ int } y: (#struct){ z: (string){ string } } n: (string){ string } depends_on: (list){ } } #A2: (#struct){ i: (string){ string } n: (string){ string } depends_on: (list){ } } s: (struct){ foo: (#struct){ x: (int){ 10 } y: (#struct){ z: (string){ "z" } } n: (string){ "foo" } depends_on: (list){ } } bar: (#struct){ i: (string){ "hello bar" } depends_on: (#list){ 0: (#struct){ x: (int){ 10 } y: (#struct){ z: (string){ "z" } } n: (string){ "foo" } depends_on: (list){ } } } n: (string){ "bar" } } } } b: (struct){ #A: (#struct){ f: (#struct){ } } #A1: (#struct){ f: (#struct){ } } #C: (#struct){ d: (#struct){ } } s: (struct){ foo: (#struct){ f: (#struct){ d: (#struct){ foo: (string){ "bar" } } } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -11,44 +11,44 @@ } } #A1: (#struct){ - n: (string){ string } - depends_on: (list){ - } x: (int){ int } y: (#struct){ z: (string){ string } } + n: (string){ string } + depends_on: (list){ + } } #A2: (#struct){ - n: (string){ string } - depends_on: (list){ - } i: (string){ string } - } - s: (struct){ - foo: (#struct){ - n: (string){ "foo" } - depends_on: (list){ - } + n: (string){ string } + depends_on: (list){ + } + } + s: (struct){ + foo: (#struct){ x: (int){ 10 } y: (#struct){ z: (string){ "z" } } + n: (string){ "foo" } + depends_on: (list){ + } } bar: (#struct){ - n: (string){ "bar" } + i: (string){ "hello bar" } depends_on: (#list){ 0: (#struct){ - n: (string){ "foo" } - depends_on: (list){ - } x: (int){ 10 } y: (#struct){ z: (string){ "z" } } - } - } - i: (string){ "hello bar" } + n: (string){ "foo" } + depends_on: (list){ + } + } + } + n: (string){ "bar" } } } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ a: (struct){ #A: (#struct){ n: (string){ string } depends_on: (list){ } } #AnyA: (#struct){ n: (string){ string } depends_on: (list){ } } #A1: (#struct){ n: (string){ string } depends_on: (list){ } x: (int){ int } y: (#struct){ z: (string){ string } } } #A2: (#struct){ n: (string){ string } depends_on: (list){ } i: (string){ string } } s: (struct){ foo: (#struct){ n: (string){ "foo" } depends_on: (list){ } x: (int){ 10 } y: (#struct){ z: (string){ "z" } } } bar: (#struct){ n: (string){ "bar" } depends_on: (#list){ 0: (#struct){ n: (string){ "foo" } depends_on: (list){ } x: (int){ 10 } y: (#struct){ z: (string){ "z" } } } } i: (string){ "hello bar" } } } } b: (struct){ #A: (#struct){ f: (#struct){ } } #A1: (#struct){ f: (#struct){ } } #C: (#struct){ d: (#struct){ } } s: (struct){ foo: (#struct){ f: (#struct){ d: (#struct){ foo: (string){ "bar" } } } } } } } -- out/compile -- --- in.cue { a: { #A: { n: string depends_on: [ ...〈2;#AnyA〉, ] } #AnyA: { n: string depends_on: [ ...〈2;#AnyA〉, ] ... } #A1: { 〈1;#A〉 x: int y: { z: string } } #A2: { 〈1;#A〉 i: string } s: { [string]: (〈1;#AnyA〉 & { n: 〈1;-〉 }) } s: { foo: (〈1;#A1〉 & { x: 10 y: { z: "z" } }) } s: { bar: (〈1;#A2〉 & { i: "hello bar" depends_on: [ 〈3;s〉.foo, ] }) } } b: { #A: { f: { ... } } #A1: { 〈1;#A〉 } #C: { d: { ... } } s: { [string]: 〈1;#A1〉 } s: { foo: { f: (〈2;#C〉 & { d: { foo: "bar" } }) } } } } cue-lang-cue-db9cc73/cue/testdata/eval/let.txtar000066400000000000000000000540521474664451600216720ustar00rootroot00000000000000-- in.cue -- let A = 3 * 3 let B = A + A let C = B + B let D = C + C let E = D + D let F = E + E b: { let G = F + F let H = G + G let I = H + H let J = I + I let K = J + J let L = K + K let M = L + L let N = M + M let O = N + N let P = O + O let Q = P + P let R = Q + Q let S = R + R let T = S + S a: T b: F } issue1828: { volumes: L3 let L3 = { for v2 in [for v1 in L2 {}] {} } let L2 = L1 let L1 = [] } ignoreErrorInLet: { let X = 1 & 2 disjunction: *X | 3 } -- incomprehension.cue -- // for comprehensions in list do not have to split the let as each instance // is already associated with a separate environment. list: { l: [ 1, 2, 3 ] c: [ for v in l { let X = v*4 // can share X } ] } referencesForDirectly: { l: [ 1, 2, 3 ] for k, v in l { let Y = v*4 // multi "\(k)": Y } } referencesForViaLet: { l: [ 1, 2, 3 ] for k, v in l let X = v*4 { let Y = X // multi "\(k)": Y } } letClauseReferencesInert: { x: 2 l: [ 1, 2, 3 ] for k, v in l let X = x { let Y = X // can share "\(k)": Y } } // for indirect references, it is okay to not "split" a let clause, as the // it will only fail as a result of not splitting if the referred values // would fail as well. indirectReference: { l: [ 1, 2, 3 ] for k, v in l { y: v // fails if v differs for each y. let X = y*4 // can share, as y fails if let fails. "\(k)": X } } nestedFor: { for k, y in [ 4, 5 ] { let X = { for x in [ 1, 2 ] { let X = x "\(X)": X } } "\(k)": X } } -- issue2166.cue -- letWithDynamicInComprehension: { _i: { a: "d" b: "e" } for k, v in _i { let T = v (T): "1" } } -- issue2218.cue -- _parent_configs: { PARENT: true } _configs: { CHILD1: { property: true } CHILD2: { property: true parent: "PARENT" } } disabled_parent_test: {for k, v in _configs { let parent_config = (*_parent_configs[v.parent] | false) "\(k)": { "parent_config": parent_config } }} -- issue2063.cue -- import ( "encoding/yaml" "strings" ) // Issue #2063 keepDescending: t1: { ec: {} bs: { let m = ec.b if m == _|_ { } x: y: "" } } keepDescending: t2: { x: yaml.Marshal(bs) ec: {} bs: { let m = ec.b if m.b == _|_ { } X: Y: strings.Join([], "") } } -- out/evalalpha/stats -- Leaks: 226 Freed: 16 Reused: 16 Allocs: 226 Retain: 0 Unifications: 210 Conjuncts: 1451 Disjuncts: 32 -- out/evalalpha -- Errors: indirectReference.y: conflicting values 2 and 1: ./incomprehension.cue:42:7 ./incomprehension.cue:42:10 indirectReference.y: conflicting values 3 and 1: ./incomprehension.cue:42:7 ./incomprehension.cue:42:13 Result: (_|_){ // [eval] let A#1 = (int){ 9 } let B#2 = (int){ 18 } let C#3 = (int){ 36 } let D#4 = (int){ 72 } let E#5 = (int){ 144 } let F#6 = (int){ 288 } b: (struct){ let G#7 = (int){ 576 } let H#8 = (int){ 1152 } let I#9 = (int){ 2304 } let J#A = (int){ 4608 } let K#B = (int){ 9216 } let L#C = (int){ 18432 } let M#D = (int){ 36864 } let N#E = (int){ 73728 } let O#F = (int){ 147456 } let P#10 = (int){ 294912 } let Q#11 = (int){ 589824 } let R#12 = (int){ 1179648 } let S#13 = (int){ 2359296 } let T#14 = (int){ 4718592 } a: (int){ 4718592 } b: (int){ 288 } } issue1828: (struct){ volumes: (struct){ } let L3#15 = (struct){ } let L2#16 = (#list){ } let L1#17 = (#list){ } } ignoreErrorInLet: (struct){ let X#18 = (_|_){ // [eval] ignoreErrorInLet.X: conflicting values 2 and 1: // ./in.cue:37:10 // ./in.cue:37:14 } disjunction: (int){ 3 } } list: (struct){ l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } c: (#list){ 0: (int){ 4 let X#19 = (int){ 4 } } 1: (int){ 8 let X#19 = (int){ 8 } } 2: (int){ 12 let X#19 = (int){ 12 } } } } referencesForDirectly: (struct){ l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } let Y#1Amulti = (〈1;v〉 * 4) "0": (int){ 4 } "1": (int){ 8 } "2": (int){ 12 } } referencesForViaLet: (struct){ l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } let Y#1Bmulti = 〈1;X〉 "0": (int){ 4 } "1": (int){ 8 } "2": (int){ 12 } } letClauseReferencesInert: (struct){ x: (int){ 2 } l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } let Y#1Cmulti = 〈1;X〉 "0": (int){ 2 } "1": (int){ 2 } "2": (int){ 2 } } indirectReference: (_|_){ // [eval] l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } y: (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 } let X#1Dmulti = (〈0;y〉 * 4) "0": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 } "1": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 } "2": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 } } nestedFor: (struct){ let X#1Emulti = { for _, x in [ 1, 2, ] { let X#1Fmulti = 〈1;x〉 "\(〈0;let X#1F〉)": 〈0;let X#1F〉 } } "0": (struct){ let X#1Fmulti = 〈1;x〉 "1": (int){ 1 } "2": (int){ 2 } } "1": (struct){ let X#1Fmulti = 〈1;x〉 "1": (int){ 1 } "2": (int){ 2 } } } keepDescending: (struct){ t1: (struct){ ec: (struct){ } bs: (struct){ let m#21 = (_|_){ // [incomplete] keepDescending.t1.bs.m: undefined field: b: // ./issue2063.cue:10:14 } x: (struct){ y: (string){ "" } } } } t2: (struct){ x: (string){ "X:\n \"Y\": \"\"\n" } ec: (struct){ } bs: (struct){ let m#22 = (_|_){ // [incomplete] keepDescending.t2.bs.m: undefined field: b: // ./issue2063.cue:21:14 } X: (struct){ Y: (string){ "" } } } } } letWithDynamicInComprehension: (struct){ _i: (struct){ a: (string){ "d" } b: (string){ "e" } } let T#23multi = 〈1;v〉 e: (string){ "1" } d: (string){ "1" } } _parent_configs: (struct){ PARENT: (bool){ true } } _configs: (struct){ CHILD1: (struct){ property: (bool){ true } } CHILD2: (struct){ property: (bool){ true } parent: (string){ "PARENT" } } } disabled_parent_test: (struct){ let parent_config#24multi = (*〈3;_parent_configs〉[〈1;v〉.parent]|false) CHILD1: (struct){ parent_config: (bool){ false } } CHILD2: (struct){ parent_config: (bool){ |(*(bool){ true }, (bool){ false }) } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,13 +2,9 @@ indirectReference.y: conflicting values 2 and 1: ./incomprehension.cue:42:7 ./incomprehension.cue:42:10 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 indirectReference.y: conflicting values 3 and 1: ./incomprehension.cue:42:7 ./incomprehension.cue:42:13 - ./incomprehension.cue:43:2 - ./incomprehension.cue:44:6 Result: (_|_){ @@ -105,7 +101,7 @@ 1: (int){ 2 } 2: (int){ 3 } } - let Y#1C = (int){ 2 } + let Y#1Cmulti = 〈1;X〉 "0": (int){ 2 } "1": (int){ 2 } "2": (int){ 2 } @@ -121,61 +117,34 @@ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - // indirectReference.y: conflicting values 3 and 1: - // ./incomprehension.cue:42:7 - // ./incomprehension.cue:42:13 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - } - let X#1D = (_|_){ - // [eval] indirectReference.y: conflicting values 2 and 1: - // ./incomprehension.cue:42:7 - // ./incomprehension.cue:42:10 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - // indirectReference.y: conflicting values 3 and 1: - // ./incomprehension.cue:42:7 - // ./incomprehension.cue:42:13 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - } + // indirectReference.y: conflicting values 3 and 1: + // ./incomprehension.cue:42:7 + // ./incomprehension.cue:42:13 + } + let X#1Dmulti = (〈0;y〉 * 4) "0": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - // indirectReference.y: conflicting values 3 and 1: - // ./incomprehension.cue:42:7 - // ./incomprehension.cue:42:13 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 + // indirectReference.y: conflicting values 3 and 1: + // ./incomprehension.cue:42:7 + // ./incomprehension.cue:42:13 } "1": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - // indirectReference.y: conflicting values 3 and 1: - // ./incomprehension.cue:42:7 - // ./incomprehension.cue:42:13 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 + // indirectReference.y: conflicting values 3 and 1: + // ./incomprehension.cue:42:7 + // ./incomprehension.cue:42:13 } "2": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 - // indirectReference.y: conflicting values 3 and 1: - // ./incomprehension.cue:42:7 - // ./incomprehension.cue:42:13 - // ./incomprehension.cue:43:2 - // ./incomprehension.cue:44:6 + // indirectReference.y: conflicting values 3 and 1: + // ./incomprehension.cue:42:7 + // ./incomprehension.cue:42:13 } } nestedFor: (struct){ @@ -234,8 +203,8 @@ b: (string){ "e" } } let T#23multi = 〈1;v〉 - d: (string){ "1" } e: (string){ "1" } + d: (string){ "1" } } _parent_configs: (struct){ PARENT: (bool){ true } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 51 -Freed: 159 -Reused: 150 -Allocs: 60 -Retain: 188 +Leaks: 226 +Freed: 16 +Reused: 16 +Allocs: 226 +Retain: 0 -Unifications: 196 -Conjuncts: 373 -Disjuncts: 248 +Unifications: 210 +Conjuncts: 1451 +Disjuncts: 32 -- out/eval/stats -- Leaks: 52 Freed: 158 Reused: 149 Allocs: 61 Retain: 184 Unifications: 196 Conjuncts: 365 Disjuncts: 241 -- out/eval -- Errors: indirectReference.y: conflicting values 2 and 1: ./incomprehension.cue:42:7 ./incomprehension.cue:42:10 ./incomprehension.cue:43:2 ./incomprehension.cue:44:6 indirectReference.y: conflicting values 3 and 1: ./incomprehension.cue:42:7 ./incomprehension.cue:42:13 ./incomprehension.cue:43:2 ./incomprehension.cue:44:6 Result: (_|_){ // [eval] let A#1 = (int){ 9 } let B#2 = (int){ 18 } let C#3 = (int){ 36 } let D#4 = (int){ 72 } let E#5 = (int){ 144 } let F#6 = (int){ 288 } b: (struct){ let G#7 = (int){ 576 } let H#8 = (int){ 1152 } let I#9 = (int){ 2304 } let J#A = (int){ 4608 } let K#B = (int){ 9216 } let L#C = (int){ 18432 } let M#D = (int){ 36864 } let N#E = (int){ 73728 } let O#F = (int){ 147456 } let P#10 = (int){ 294912 } let Q#11 = (int){ 589824 } let R#12 = (int){ 1179648 } let S#13 = (int){ 2359296 } let T#14 = (int){ 4718592 } a: (int){ 4718592 } b: (int){ 288 } } issue1828: (struct){ volumes: (struct){ } let L3#15 = (struct){ } let L2#16 = (#list){ } let L1#17 = (#list){ } } ignoreErrorInLet: (struct){ let X#18 = (_|_){ // [eval] ignoreErrorInLet.X: conflicting values 2 and 1: // ./in.cue:37:10 // ./in.cue:37:14 } disjunction: (int){ 3 } } list: (struct){ l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } c: (#list){ 0: (int){ 4 let X#19 = (int){ 4 } } 1: (int){ 8 let X#19 = (int){ 8 } } 2: (int){ 12 let X#19 = (int){ 12 } } } } referencesForDirectly: (struct){ l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } let Y#1Amulti = (〈1;v〉 * 4) "0": (int){ 4 } "1": (int){ 8 } "2": (int){ 12 } } referencesForViaLet: (struct){ l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } let Y#1Bmulti = 〈1;X〉 "0": (int){ 4 } "1": (int){ 8 } "2": (int){ 12 } } letClauseReferencesInert: (struct){ x: (int){ 2 } l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } let Y#1C = (int){ 2 } "0": (int){ 2 } "1": (int){ 2 } "2": (int){ 2 } } indirectReference: (_|_){ // [eval] l: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } y: (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 } let X#1D = (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 } "0": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 } "1": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 } "2": (_|_){ // [eval] indirectReference.y: conflicting values 2 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:10 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 // indirectReference.y: conflicting values 3 and 1: // ./incomprehension.cue:42:7 // ./incomprehension.cue:42:13 // ./incomprehension.cue:43:2 // ./incomprehension.cue:44:6 } } nestedFor: (struct){ let X#1Emulti = { for _, x in [ 1, 2, ] { let X#1Fmulti = 〈1;x〉 "\(〈0;let X#1F〉)": 〈0;let X#1F〉 } } "0": (struct){ let X#1Fmulti = 〈1;x〉 "1": (int){ 1 } "2": (int){ 2 } } "1": (struct){ let X#1Fmulti = 〈1;x〉 "1": (int){ 1 } "2": (int){ 2 } } } keepDescending: (struct){ t1: (struct){ ec: (struct){ } bs: (struct){ let m#21 = (_|_){ // [incomplete] keepDescending.t1.bs.m: undefined field: b: // ./issue2063.cue:10:14 } x: (struct){ y: (string){ "" } } } } t2: (struct){ x: (string){ "X:\n \"Y\": \"\"\n" } ec: (struct){ } bs: (struct){ let m#22 = (_|_){ // [incomplete] keepDescending.t2.bs.m: undefined field: b: // ./issue2063.cue:21:14 } X: (struct){ Y: (string){ "" } } } } } letWithDynamicInComprehension: (struct){ _i: (struct){ a: (string){ "d" } b: (string){ "e" } } let T#23multi = 〈1;v〉 d: (string){ "1" } e: (string){ "1" } } _parent_configs: (struct){ PARENT: (bool){ true } } _configs: (struct){ CHILD1: (struct){ property: (bool){ true } } CHILD2: (struct){ property: (bool){ true } parent: (string){ "PARENT" } } } disabled_parent_test: (struct){ let parent_config#24multi = (*〈3;_parent_configs〉[〈1;v〉.parent]|false) CHILD1: (struct){ parent_config: (bool){ false } } CHILD2: (struct){ parent_config: (bool){ |(*(bool){ true }, (bool){ false }) } } } } -- out/compile -- --- in.cue { let A#1 = (3 * 3) let B#2 = (〈0;let A#1〉 + 〈0;let A#1〉) let C#3 = (〈0;let B#2〉 + 〈0;let B#2〉) let D#4 = (〈0;let C#3〉 + 〈0;let C#3〉) let E#5 = (〈0;let D#4〉 + 〈0;let D#4〉) let F#6 = (〈0;let E#5〉 + 〈0;let E#5〉) b: { let G#7 = (〈1;let F#6〉 + 〈1;let F#6〉) let H#8 = (〈0;let G#7〉 + 〈0;let G#7〉) let I#9 = (〈0;let H#8〉 + 〈0;let H#8〉) let J#A = (〈0;let I#9〉 + 〈0;let I#9〉) let K#B = (〈0;let J#A〉 + 〈0;let J#A〉) let L#C = (〈0;let K#B〉 + 〈0;let K#B〉) let M#D = (〈0;let L#C〉 + 〈0;let L#C〉) let N#E = (〈0;let M#D〉 + 〈0;let M#D〉) let O#F = (〈0;let N#E〉 + 〈0;let N#E〉) let P#10 = (〈0;let O#F〉 + 〈0;let O#F〉) let Q#11 = (〈0;let P#10〉 + 〈0;let P#10〉) let R#12 = (〈0;let Q#11〉 + 〈0;let Q#11〉) let S#13 = (〈0;let R#12〉 + 〈0;let R#12〉) let T#14 = (〈0;let S#13〉 + 〈0;let S#13〉) a: 〈0;let T#14〉 b: 〈1;let F#6〉 } issue1828: { volumes: 〈0;let L3#15〉 let L3#15 = { for _, v2 in [ for _, v1 in 〈2;let L2#16〉 {}, ] {} } let L2#16 = 〈0;let L1#17〉 let L1#17 = [] } ignoreErrorInLet: { let X#18 = (1 & 2) disjunction: (*〈0;let X#18〉|3) } } --- incomprehension.cue { list: { l: [ 1, 2, 3, ] c: [ for _, v in 〈1;l〉 { let X#19 = (〈1;v〉 * 4) 〈0;let X#19〉 }, ] } referencesForDirectly: { l: [ 1, 2, 3, ] for k, v in 〈0;l〉 { let Y#1Amulti = (〈1;v〉 * 4) "\(〈1;k〉)": 〈0;let Y#1A〉 } } referencesForViaLet: { l: [ 1, 2, 3, ] for k, v in 〈0;l〉 let X = (〈0;v〉 * 4) { let Y#1Bmulti = 〈1;X〉 "\(〈2;k〉)": 〈0;let Y#1B〉 } } letClauseReferencesInert: { x: 2 l: [ 1, 2, 3, ] for k, v in 〈0;l〉 let X = 〈1;x〉 { let Y#1C = 〈1;X〉 "\(〈2;k〉)": 〈0;let Y#1C〉 } } indirectReference: { l: [ 1, 2, 3, ] for k, v in 〈0;l〉 { y: 〈1;v〉 let X#1D = (〈0;y〉 * 4) "\(〈1;k〉)": 〈0;let X#1D〉 } } nestedFor: { for k, y in [ 4, 5, ] { let X#1Emulti = { for _, x in [ 1, 2, ] { let X#1Fmulti = 〈1;x〉 "\(〈0;let X#1F〉)": 〈0;let X#1F〉 } } "\(〈1;k〉)": 〈0;let X#1E〉 } } } --- issue2063.cue { keepDescending: { t1: { ec: {} bs: { let m#21 = 〈1;ec〉.b if (〈0;let m#21〉 == _|_(explicit error (_|_ literal) in source)) {} x: { y: "" } } } } keepDescending: { t2: { x: 〈import;"encoding/yaml"〉.Marshal(〈0;bs〉) ec: {} bs: { let m#22 = 〈1;ec〉.b if (〈0;let m#22〉.b == _|_(explicit error (_|_ literal) in source)) {} X: { Y: 〈import;strings〉.Join([], "") } } } } } --- issue2166.cue { letWithDynamicInComprehension: { _i: { a: "d" b: "e" } for k, v in 〈0;_i〉 { let T#23multi = 〈1;v〉 〈0;let T#23〉: "1" } } } --- issue2218.cue { _parent_configs: { PARENT: true } _configs: { CHILD1: { property: true } CHILD2: { property: true parent: "PARENT" } } disabled_parent_test: { for k, v in 〈1;_configs〉 { let parent_config#24multi = (*〈3;_parent_configs〉[〈1;v〉.parent]|false) "\(〈1;k〉)": { parent_config: 〈1;let parent_config#24〉 } } } } cue-lang-cue-db9cc73/cue/testdata/eval/letjoin.txtar000066400000000000000000000357571474664451600225650ustar00rootroot00000000000000-- in.cue -- // Test that an error in a let that is merged with itself from two different // origins does not result in an error as long as the error is not referenced // outside the let. t1: { x: { a: int y: { let X = { b: a c: 1 } v: X.c } } x1: x x1: a: 1 x2: x x2: a: 2 xy: x1.y & x2.y } t2: { x: { a: {} y: { let X = { b: a c: 1 } v: X.c } } x1: x x1: a: q: 1 x2: x x2: a: r: 2 xy: x1 & x2 } -- issue3590.cue -- issue3590: reduced: { result: [_]: [string]: string _input: { A: p: "A" B: p: "B" } for _, v in _input { let Var1 = v.p // Second let variable required here; just using Var1 with Items not // sufficient let Var2 = Var1 let Items = { item: Var2 } result: "conflicting-\(v.p)": Items } } issue3590: full: { #Result: [_]: {[string]: string} result: #Result #Input: { p: "A" | "B" } _input: [Parm=_]: #Input & { p: Parm } _input: { A: {} B: {} } for _, v in _input { let Var1 = v.p let Var2 = Var1 let Items = { "item": Var2 } result: "conflicting-\(v.p)": Items } } // Issue #3591 is related issue3591: missing: { #Result: [_]: {[string]: string} result: #Result #Input: { p: "A" | "B" } _input: [Parm=_]: #Input & { p: Parm } _input: { A: {} B: {} } for _, v in _input { let Var1 = v.p let Var2 = Var1 let Items = { "item": { key1: Var2 } } result: "missing-items-\(v.p)": { for s, attr in Items { if attr.key1 != _|_ {(s): attr.key1} } } } } -- out/evalalpha/stats -- Leaks: 202 Freed: 20 Reused: 19 Allocs: 203 Retain: 0 Unifications: 178 Conjuncts: 1209 Disjuncts: 36 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 24 -Freed: 219 -Reused: 207 -Allocs: 36 -Retain: 160 +Leaks: 202 +Freed: 20 +Reused: 19 +Allocs: 203 +Retain: 0 -Unifications: 167 -Conjuncts: 486 -Disjuncts: 325 +Unifications: 178 +Conjuncts: 1209 +Disjuncts: 36 -- out/eval/stats -- Leaks: 24 Freed: 219 Reused: 207 Allocs: 36 Retain: 160 Unifications: 167 Conjuncts: 486 Disjuncts: 325 -- out/evalalpha -- (struct){ t1: (struct){ x: (struct){ a: (int){ int } y: (struct){ let X#1 = (struct){ b: (int){ int } c: (int){ 1 } } v: (int){ 1 } } } x1: (struct){ a: (int){ 1 } y: (struct){ let X#1 = (struct){ b: (int){ 1 } c: (int){ 1 } } v: (int){ 1 } } } x2: (struct){ a: (int){ 2 } y: (struct){ let X#1 = (struct){ b: (int){ 2 } c: (int){ 1 } } v: (int){ 1 } } } xy: (struct){ let X#1multi = { b: 〈2;a〉 c: 1 } v: (int){ 1 } } } t2: (struct){ x: (struct){ a: (struct){ } y: (struct){ let X#2 = (struct){ b: (struct){ } c: (int){ 1 } } v: (int){ 1 } } } x1: (struct){ a: (struct){ q: (int){ 1 } } y: (struct){ let X#2 = (struct){ b: ~(t2.x1.a) c: (int){ 1 } } v: (int){ 1 } } } x2: (struct){ a: (struct){ r: (int){ 2 } } y: (struct){ let X#2 = (struct){ b: ~(t2.x2.a) c: (int){ 1 } } v: (int){ 1 } } } xy: (struct){ a: (struct){ q: (int){ 1 } r: (int){ 2 } } y: (struct){ let X#2multi = { b: 〈2;a〉 c: 1 } v: (int){ 1 } } } } issue3590: (struct){ reduced: (struct){ result: (struct){ "conflicting-A": (struct){ item: (string){ "A" } } "conflicting-B": (struct){ item: (string){ "B" } } } _input: (struct){ A: (struct){ p: (string){ "A" } } B: (struct){ p: (string){ "B" } } } let Var1#3multi = 〈1;v〉.p let Var2#4multi = 〈0;let Var1#3〉 let Items#5multi = { item: 〈1;let Var2#4〉 } } full: (struct){ #Result: (#struct){ } result: (#struct){ "conflicting-A": (#struct){ item: (string){ "A" } } "conflicting-B": (#struct){ item: (string){ "B" } } } #Input: (#struct){ p: (string){ |((string){ "A" }, (string){ "B" }) } } _input: (struct){ A: (#struct){ p: (string){ "A" } } B: (#struct){ p: (string){ "B" } } } let Var1#6multi = 〈1;v〉.p let Var2#7multi = 〈0;let Var1#6〉 let Items#8multi = { item: 〈1;let Var2#7〉 } } } issue3591: (struct){ missing: (struct){ #Result: (#struct){ } result: (#struct){ "missing-items-A": (#struct){ item: (string){ "A" } } "missing-items-B": (#struct){ item: (string){ "B" } } } #Input: (#struct){ p: (string){ |((string){ "A" }, (string){ "B" }) } } _input: (struct){ A: (#struct){ p: (string){ "A" } } B: (#struct){ p: (string){ "B" } } } let Var1#9multi = 〈1;v〉.p let Var2#Amulti = 〈0;let Var1#9〉 let Items#Bmulti = { item: { key1: 〈2;let Var2#A〉 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -57,23 +57,19 @@ } y: (struct){ let X#2 = (struct){ - b: (struct){ - q: (int){ 1 } - } - c: (int){ 1 } - } - v: (int){ 1 } - } - } - x2: (struct){ - a: (struct){ - r: (int){ 2 } - } - y: (struct){ - let X#2 = (struct){ - b: (struct){ - r: (int){ 2 } - } + b: ~(t2.x1.a) + c: (int){ 1 } + } + v: (int){ 1 } + } + } + x2: (struct){ + a: (struct){ + r: (int){ 2 } + } + y: (struct){ + let X#2 = (struct){ + b: ~(t2.x2.a) c: (int){ 1 } } v: (int){ 1 } @@ -113,17 +109,8 @@ } let Var1#3multi = 〈1;v〉.p let Var2#4multi = 〈0;let Var1#3〉 - let Items#5 = (_|_){ - // [eval] - item: (_|_){ - // [eval] issue3590.reduced.Items.item: conflicting values "B" and "A": - // ./issue3590.cue:5:9 - // ./issue3590.cue:6:9 - // ./issue3590.cue:9:2 - // ./issue3590.cue:10:14 - // ./issue3590.cue:14:14 - // ./issue3590.cue:17:10 - } + let Items#5multi = { + item: 〈1;let Var2#4〉 } } full: (struct){ @@ -150,16 +137,8 @@ } let Var1#6multi = 〈1;v〉.p let Var2#7multi = 〈0;let Var1#6〉 - let Items#8 = (_|_){ - // [eval] - item: (_|_){ - // [eval] issue3590.full.Items.item: conflicting values "B" and "A": - // ./issue3590.cue:33:6 - // ./issue3590.cue:41:2 - // ./issue3590.cue:42:14 - // ./issue3590.cue:43:14 - // ./issue3590.cue:46:12 - } + let Items#8multi = { + item: 〈1;let Var2#7〉 } } } @@ -188,18 +167,9 @@ } let Var1#9multi = 〈1;v〉.p let Var2#Amulti = 〈0;let Var1#9〉 - let Items#B = (_|_){ - // [eval] - item: (_|_){ - // [eval] - key1: (_|_){ - // [eval] issue3591.missing.Items.item.key1: conflicting values "B" and "A": - // ./issue3590.cue:63:6 - // ./issue3590.cue:71:2 - // ./issue3590.cue:72:14 - // ./issue3590.cue:73:14 - // ./issue3590.cue:77:11 - } + let Items#Bmulti = { + item: { + key1: 〈2;let Var2#A〉 } } } -- diff/todo/p4 -- Reduce conjunct group size. Semantically correct, though. -- out/eval -- (struct){ t1: (struct){ x: (struct){ a: (int){ int } y: (struct){ let X#1 = (struct){ b: (int){ int } c: (int){ 1 } } v: (int){ 1 } } } x1: (struct){ a: (int){ 1 } y: (struct){ let X#1 = (struct){ b: (int){ 1 } c: (int){ 1 } } v: (int){ 1 } } } x2: (struct){ a: (int){ 2 } y: (struct){ let X#1 = (struct){ b: (int){ 2 } c: (int){ 1 } } v: (int){ 1 } } } xy: (struct){ let X#1multi = { b: 〈2;a〉 c: 1 } v: (int){ 1 } } } t2: (struct){ x: (struct){ a: (struct){ } y: (struct){ let X#2 = (struct){ b: (struct){ } c: (int){ 1 } } v: (int){ 1 } } } x1: (struct){ a: (struct){ q: (int){ 1 } } y: (struct){ let X#2 = (struct){ b: (struct){ q: (int){ 1 } } c: (int){ 1 } } v: (int){ 1 } } } x2: (struct){ a: (struct){ r: (int){ 2 } } y: (struct){ let X#2 = (struct){ b: (struct){ r: (int){ 2 } } c: (int){ 1 } } v: (int){ 1 } } } xy: (struct){ a: (struct){ q: (int){ 1 } r: (int){ 2 } } y: (struct){ let X#2multi = { b: 〈2;a〉 c: 1 } v: (int){ 1 } } } } issue3590: (struct){ reduced: (struct){ result: (struct){ "conflicting-A": (struct){ item: (string){ "A" } } "conflicting-B": (struct){ item: (string){ "B" } } } _input: (struct){ A: (struct){ p: (string){ "A" } } B: (struct){ p: (string){ "B" } } } let Var1#3multi = 〈1;v〉.p let Var2#4multi = 〈0;let Var1#3〉 let Items#5 = (_|_){ // [eval] item: (_|_){ // [eval] issue3590.reduced.Items.item: conflicting values "B" and "A": // ./issue3590.cue:5:9 // ./issue3590.cue:6:9 // ./issue3590.cue:9:2 // ./issue3590.cue:10:14 // ./issue3590.cue:14:14 // ./issue3590.cue:17:10 } } } full: (struct){ #Result: (#struct){ } result: (#struct){ "conflicting-A": (#struct){ item: (string){ "A" } } "conflicting-B": (#struct){ item: (string){ "B" } } } #Input: (#struct){ p: (string){ |((string){ "A" }, (string){ "B" }) } } _input: (struct){ A: (#struct){ p: (string){ "A" } } B: (#struct){ p: (string){ "B" } } } let Var1#6multi = 〈1;v〉.p let Var2#7multi = 〈0;let Var1#6〉 let Items#8 = (_|_){ // [eval] item: (_|_){ // [eval] issue3590.full.Items.item: conflicting values "B" and "A": // ./issue3590.cue:33:6 // ./issue3590.cue:41:2 // ./issue3590.cue:42:14 // ./issue3590.cue:43:14 // ./issue3590.cue:46:12 } } } } issue3591: (struct){ missing: (struct){ #Result: (#struct){ } result: (#struct){ "missing-items-A": (#struct){ item: (string){ "A" } } "missing-items-B": (#struct){ item: (string){ "B" } } } #Input: (#struct){ p: (string){ |((string){ "A" }, (string){ "B" }) } } _input: (struct){ A: (#struct){ p: (string){ "A" } } B: (#struct){ p: (string){ "B" } } } let Var1#9multi = 〈1;v〉.p let Var2#Amulti = 〈0;let Var1#9〉 let Items#B = (_|_){ // [eval] item: (_|_){ // [eval] key1: (_|_){ // [eval] issue3591.missing.Items.item.key1: conflicting values "B" and "A": // ./issue3590.cue:63:6 // ./issue3590.cue:71:2 // ./issue3590.cue:72:14 // ./issue3590.cue:73:14 // ./issue3590.cue:77:11 } } } } } } -- out/compile -- --- in.cue { t1: { x: { a: int y: { let X#1 = { b: 〈2;a〉 c: 1 } v: 〈0;let X#1〉.c } } x1: 〈0;x〉 x1: { a: 1 } x2: 〈0;x〉 x2: { a: 2 } xy: (〈0;x1〉.y & 〈0;x2〉.y) } t2: { x: { a: {} y: { let X#2 = { b: 〈2;a〉 c: 1 } v: 〈0;let X#2〉.c } } x1: 〈0;x〉 x1: { a: { q: 1 } } x2: 〈0;x〉 x2: { a: { r: 2 } } xy: (〈0;x1〉 & 〈0;x2〉) } } --- issue3590.cue { issue3590: { reduced: { result: { [_]: { [string]: string } } _input: { A: { p: "A" } B: { p: "B" } } for _, v in 〈0;_input〉 { let Var1#3multi = 〈1;v〉.p let Var2#4multi = 〈0;let Var1#3〉 let Items#5 = { item: 〈1;let Var2#4〉 } result: { "conflicting-\(〈2;v〉.p)": 〈1;let Items#5〉 } } } } issue3590: { full: { #Result: { [_]: { [string]: string } } result: 〈0;#Result〉 #Input: { p: ("A"|"B") } _input: { [_]: (〈1;#Input〉 & { p: 〈1;-〉 }) } _input: { A: {} B: {} } for _, v in 〈0;_input〉 { let Var1#6multi = 〈1;v〉.p let Var2#7multi = 〈0;let Var1#6〉 let Items#8 = { item: 〈1;let Var2#7〉 } result: { "conflicting-\(〈2;v〉.p)": 〈1;let Items#8〉 } } } } issue3591: { missing: { #Result: { [_]: { [string]: string } } result: 〈0;#Result〉 #Input: { p: ("A"|"B") } _input: { [_]: (〈1;#Input〉 & { p: 〈1;-〉 }) } _input: { A: {} B: {} } for _, v in 〈0;_input〉 { let Var1#9multi = 〈1;v〉.p let Var2#Amulti = 〈0;let Var1#9〉 let Items#B = { item: { key1: 〈2;let Var2#A〉 } } result: { "missing-items-\(〈2;v〉.p)": { for s, attr in 〈2;let Items#B〉 { if (〈1;attr〉.key1 != _|_(explicit error (_|_ literal) in source)) { 〈2;s〉: 〈2;attr〉.key1 } } } } } } } } cue-lang-cue-db9cc73/cue/testdata/eval/lists.txtar000066400000000000000000000013141474664451600222350ustar00rootroot00000000000000-- in.cue -- a: [...int] a: [1, 2, 3, 5] a: [1, 2, 3, d] b: a[3] d: 5 c: [for x in [[1, 2]][0] {x + d}] -- out/eval/stats -- Leaks: 4 Freed: 11 Reused: 8 Allocs: 7 Retain: 6 Unifications: 15 Conjuncts: 29 Disjuncts: 13 -- out/eval -- (struct){ a: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } 3: (int){ 5 } } b: (int){ 5 } d: (int){ 5 } c: (#list){ 0: (int){ 6 } 1: (int){ 7 } } } -- out/compile -- --- in.cue { a: [ ...int, ] a: [ 1, 2, 3, 5, ] a: [ 1, 2, 3, 〈1;d〉, ] b: 〈0;a〉[3] d: 5 c: [ for _, x in [ [ 1, 2, ], ][0] { (〈1;x〉 + 〈3;d〉) }, ] } cue-lang-cue-db9cc73/cue/testdata/eval/merge.txtar000066400000000000000000000035371474664451600222070ustar00rootroot00000000000000TODO: image field is not pre-evaluated (not a huge deal) TODO: allow dynamic fields -- in.cue -- key: "app01" manifests: [ { deployment: #map: [string]: {name: string, image: string, desc: string} deployment: #map: "\(key)": name: "app01" }, { deployment: #map: app01: image: "image01" // TODO: allow // deployment: #map: "\("app03")": image: "image01" }, ] // unify results: _ for _, manifest in manifests { results: manifest } -- out/eval/stats -- Leaks: 0 Freed: 22 Reused: 15 Allocs: 7 Retain: 0 Unifications: 22 Conjuncts: 38 Disjuncts: 22 -- out/eval -- (struct){ key: (string){ "app01" } manifests: (#list){ 0: (struct){ deployment: (struct){ #map: (#struct){ app01: (#struct){ name: (string){ "app01" } image: (string){ string } desc: (string){ string } } } } } 1: (struct){ deployment: (struct){ #map: (#struct){ app01: (#struct){ image: (string){ "image01" } } } } } } results: (struct){ deployment: (struct){ #map: (#struct){ app01: (#struct){ image: (string){ "image01" } name: (string){ "app01" } desc: (string){ string } } } } } } -- out/compile -- --- in.cue { key: "app01" manifests: [ { deployment: { #map: { [string]: { name: string image: string desc: string } } } deployment: { #map: { "\(〈4;key〉)": { name: "app01" } } } }, { deployment: { #map: { app01: { image: "image01" } } } }, ] results: _ for _, manifest in 〈0;manifests〉 { results: 〈1;manifest〉 } } cue-lang-cue-db9cc73/cue/testdata/eval/notify.txtar000066400000000000000000004167251474664451600224270ustar00rootroot00000000000000 -- in.cue -- t1: p1: { a a: a: 2|1 } t1: p2: { a: a: 2|1 a } t2: p1: { d: d.a d: a: a: 2|1 } t2: p2: { d: d.a d: a: a: 2|1 } t3: p1: { b: a b: (1|2) | 2 a: 1 | 2 } t3: p2: { b: (1|2) | 2 a: 1 | 2 b: a } -- issue3437.cue -- issue3437: { r: L=L.a d: a: a: a: {b: 4}|d out: r&d } -- out/evalalpha -- Errors: t1.p1: 7 errors in empty disjunction: t1.p1: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:3:5 ./in.cue:3:10 t1.p1: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:3:5 ./in.cue:3:8 t1.p1.a: 4 errors in empty disjunction: t1.p1.a: cannot combine regular field "a" with 1: ./in.cue:3:10 t1.p1.a: cannot combine regular field "a" with 2: ./in.cue:3:8 t1.p1.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:3:5 ./in.cue:3:10 t1.p1.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:3:5 ./in.cue:3:8 t1.p2: 7 errors in empty disjunction: t1.p2: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:10 t1.p2: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:8 t1.p2.a: 4 errors in empty disjunction: t1.p2.a: cannot combine regular field "a" with 1: ./in.cue:6:10 t1.p2.a: cannot combine regular field "a" with 2: ./in.cue:6:8 t1.p2.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:10 t1.p2.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:8 t2.p1.d: 7 errors in empty disjunction: t2.p1.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:11:8 ./in.cue:11:13 t2.p1.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:11:8 ./in.cue:11:11 t2.p1.d.a: 4 errors in empty disjunction: t2.p1.d.a: cannot combine regular field "a" with 1: ./in.cue:11:13 t2.p1.d.a: cannot combine regular field "a" with 2: ./in.cue:11:11 t2.p1.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:11:8 ./in.cue:11:13 t2.p1.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:11:8 ./in.cue:11:11 t2.p2.d: 7 errors in empty disjunction: t2.p2.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:15:8 ./in.cue:15:13 t2.p2.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:15:8 ./in.cue:15:11 t2.p2.d.a: 4 errors in empty disjunction: t2.p2.d.a: cannot combine regular field "a" with 1: ./in.cue:15:13 t2.p2.d.a: cannot combine regular field "a" with 2: ./in.cue:15:11 t2.p2.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:15:8 ./in.cue:15:13 t2.p2.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:15:8 ./in.cue:15:11 Result: (_|_){ // [eval] t1: (_|_){ // [eval] p1: (_|_){ // [eval] t1.p1: 7 errors in empty disjunction: // t1.p1: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:3:5 // ./in.cue:3:10 // t1.p1: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:3:5 // ./in.cue:3:8 // t1.p1.a: 4 errors in empty disjunction: // t1.p1.a: cannot combine regular field "a" with 1: // ./in.cue:3:10 // t1.p1.a: cannot combine regular field "a" with 2: // ./in.cue:3:8 // t1.p1.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:3:5 // ./in.cue:3:10 // t1.p1.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:3:5 // ./in.cue:3:8 a: (struct){ a: (_){ _ } } } p2: (_|_){ // [eval] t1.p2: 7 errors in empty disjunction: // t1.p2: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:10 // t1.p2: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:8 // t1.p2.a: 4 errors in empty disjunction: // t1.p2.a: cannot combine regular field "a" with 1: // ./in.cue:6:10 // t1.p2.a: cannot combine regular field "a" with 2: // ./in.cue:6:8 // t1.p2.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:10 // t1.p2.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:8 a: (struct){ a: (_){ _ } } } } t2: (_|_){ // [eval] p1: (_|_){ // [eval] d: (_|_){ // [eval] t2.p1.d: 7 errors in empty disjunction: // t2.p1.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:11:8 // ./in.cue:11:13 // t2.p1.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:11:8 // ./in.cue:11:11 // t2.p1.d.a: 4 errors in empty disjunction: // t2.p1.d.a: cannot combine regular field "a" with 1: // ./in.cue:11:13 // t2.p1.d.a: cannot combine regular field "a" with 2: // ./in.cue:11:11 // t2.p1.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:11:8 // ./in.cue:11:13 // t2.p1.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:11:8 // ./in.cue:11:11 a: (struct){ a: (_){ _ } } } } p2: (_|_){ // [eval] d: (_|_){ // [eval] t2.p2.d: 7 errors in empty disjunction: // t2.p2.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:15:8 // ./in.cue:15:13 // t2.p2.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:15:8 // ./in.cue:15:11 // t2.p2.d.a: 4 errors in empty disjunction: // t2.p2.d.a: cannot combine regular field "a" with 1: // ./in.cue:15:13 // t2.p2.d.a: cannot combine regular field "a" with 2: // ./in.cue:15:11 // t2.p2.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:15:8 // ./in.cue:15:13 // t2.p2.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:15:8 // ./in.cue:15:11 a: (struct){ a: (_){ _ } } } } } t3: (struct){ p1: (struct){ b: (int){ |((int){ 1 }, (int){ 2 }) } a: (int){ |((int){ 1 }, (int){ 2 }) } } p2: (struct){ b: (int){ |((int){ 1 }, (int){ 2 }) } a: (int){ |((int){ 1 }, (int){ 2 }) } } } issue3437: (struct){ r: (_){ _ } d: (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } } out: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } }) } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } } }) } }) } }) } }) } }) } }) } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ b: (int){ 4 } a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ b: (int){ 4 } a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } }) } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ b: (int){ 4 } a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } }) } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ b: (int){ 4 } a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } } }) } }) } }) } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ b: (int){ 4 } a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } } }) } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } b: (int){ 4 } } }) } b: (int){ 4 } }, (struct){ a: (struct){ |((struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } } b: (int){ 4 } } }) } }) } }) } }) } }) } }) } }) } }) } }) } } } -- out/compile -- --- in.cue { t1: { p1: { 〈0;a〉 a: { a: (2|1) } } } t1: { p2: { a: { a: (2|1) } 〈0;a〉 } } t2: { p1: { d: 〈0;d〉.a d: { a: { a: (2|1) } } } } t2: { p2: { d: 〈0;d〉.a d: { a: { a: (2|1) } } } } t3: { p1: { b: 〈0;a〉 b: ((1|2)|2) a: (1|2) } } t3: { p2: { b: ((1|2)|2) a: (1|2) b: 〈0;a〉 } } } --- issue3437.cue { issue3437: { r: 〈0〉.a d: { a: { a: { a: ({ b: 4 }|〈3;d〉) } } } out: (〈0;r〉 & 〈0;d〉) } } -- out/evalalpha/stats -- Leaks: 2262 Freed: 253 Reused: 252 Allocs: 2263 Retain: 0 Unifications: 760 Conjuncts: 13707 Disjuncts: 908 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 34 -Freed: 97 -Reused: 85 -Allocs: 46 -Retain: 5 +Leaks: 2262 +Freed: 253 +Reused: 252 +Allocs: 2263 +Retain: 0 -Unifications: 48 -Conjuncts: 150 -Disjuncts: 111 +Unifications: 760 +Conjuncts: 13707 +Disjuncts: 908 -- out/eval/stats -- Leaks: 34 Freed: 97 Reused: 85 Allocs: 46 Retain: 5 Unifications: 48 Conjuncts: 150 Disjuncts: 111 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,38 +1,74 @@ Errors: -t1.p1: 2 errors in empty disjunction: +t1.p1: 7 errors in empty disjunction: t1.p1: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): - ./in.cue:2:2 ./in.cue:3:5 ./in.cue:3:10 t1.p1: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): - ./in.cue:2:2 - ./in.cue:3:5 - ./in.cue:3:8 -t1.p2: 2 errors in empty disjunction: + ./in.cue:3:5 + ./in.cue:3:8 +t1.p1.a: 4 errors in empty disjunction: +t1.p1.a: cannot combine regular field "a" with 1: + ./in.cue:3:10 +t1.p1.a: cannot combine regular field "a" with 2: + ./in.cue:3:8 +t1.p1.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:3:5 + ./in.cue:3:10 +t1.p1.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:3:5 + ./in.cue:3:8 +t1.p2: 7 errors in empty disjunction: t1.p2: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:10 - ./in.cue:7:2 t1.p2: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:8 - ./in.cue:7:2 -t2.p1.d: 2 errors in empty disjunction: +t1.p2.a: 4 errors in empty disjunction: +t1.p2.a: cannot combine regular field "a" with 1: + ./in.cue:6:10 +t1.p2.a: cannot combine regular field "a" with 2: + ./in.cue:6:8 +t1.p2.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:6:5 + ./in.cue:6:10 +t1.p2.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:6:5 + ./in.cue:6:8 +t2.p1.d: 7 errors in empty disjunction: t2.p1.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): - ./in.cue:10:5 ./in.cue:11:8 ./in.cue:11:13 t2.p1.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): - ./in.cue:10:5 - ./in.cue:11:8 - ./in.cue:11:11 -t2.p2.d: 2 errors in empty disjunction: + ./in.cue:11:8 + ./in.cue:11:11 +t2.p1.d.a: 4 errors in empty disjunction: +t2.p1.d.a: cannot combine regular field "a" with 1: + ./in.cue:11:13 +t2.p1.d.a: cannot combine regular field "a" with 2: + ./in.cue:11:11 +t2.p1.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:11:8 + ./in.cue:11:13 +t2.p1.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:11:8 + ./in.cue:11:11 +t2.p2.d: 7 errors in empty disjunction: t2.p2.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): - ./in.cue:14:5 ./in.cue:15:8 ./in.cue:15:13 t2.p2.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): - ./in.cue:14:5 + ./in.cue:15:8 + ./in.cue:15:11 +t2.p2.d.a: 4 errors in empty disjunction: +t2.p2.d.a: cannot combine regular field "a" with 1: + ./in.cue:15:13 +t2.p2.d.a: cannot combine regular field "a" with 2: + ./in.cue:15:11 +t2.p2.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + ./in.cue:15:8 + ./in.cue:15:13 +t2.p2.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:15:8 ./in.cue:15:11 @@ -42,31 +78,49 @@ t1: (_|_){ // [eval] p1: (_|_){ - // [eval] t1.p1: 2 errors in empty disjunction: + // [eval] t1.p1: 7 errors in empty disjunction: // t1.p1: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): - // ./in.cue:2:2 // ./in.cue:3:5 // ./in.cue:3:10 // t1.p1: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): - // ./in.cue:2:2 - // ./in.cue:3:5 - // ./in.cue:3:8 - a: (struct){ - a: (int){ |((int){ 2 }, (int){ 1 }) } - } - } - p2: (_|_){ - // [eval] t1.p2: 2 errors in empty disjunction: + // ./in.cue:3:5 + // ./in.cue:3:8 + // t1.p1.a: 4 errors in empty disjunction: + // t1.p1.a: cannot combine regular field "a" with 1: + // ./in.cue:3:10 + // t1.p1.a: cannot combine regular field "a" with 2: + // ./in.cue:3:8 + // t1.p1.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:3:5 + // ./in.cue:3:10 + // t1.p1.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:3:5 + // ./in.cue:3:8 + a: (struct){ + a: (_){ _ } + } + } + p2: (_|_){ + // [eval] t1.p2: 7 errors in empty disjunction: // t1.p2: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:10 - // ./in.cue:7:2 // t1.p2: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:8 - // ./in.cue:7:2 - a: (struct){ - a: (int){ |((int){ 2 }, (int){ 1 }) } + // t1.p2.a: 4 errors in empty disjunction: + // t1.p2.a: cannot combine regular field "a" with 1: + // ./in.cue:6:10 + // t1.p2.a: cannot combine regular field "a" with 2: + // ./in.cue:6:8 + // t1.p2.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:6:5 + // ./in.cue:6:10 + // t1.p2.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:6:5 + // ./in.cue:6:8 + a: (struct){ + a: (_){ _ } } } } @@ -75,34 +129,52 @@ p1: (_|_){ // [eval] d: (_|_){ - // [eval] t2.p1.d: 2 errors in empty disjunction: + // [eval] t2.p1.d: 7 errors in empty disjunction: // t2.p1.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): - // ./in.cue:10:5 // ./in.cue:11:8 // ./in.cue:11:13 // t2.p1.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): - // ./in.cue:10:5 - // ./in.cue:11:8 - // ./in.cue:11:11 - a: (struct){ - a: (int){ |((int){ 2 }, (int){ 1 }) } - } - } - } - p2: (_|_){ - // [eval] - d: (_|_){ - // [eval] t2.p2.d: 2 errors in empty disjunction: + // ./in.cue:11:8 + // ./in.cue:11:11 + // t2.p1.d.a: 4 errors in empty disjunction: + // t2.p1.d.a: cannot combine regular field "a" with 1: + // ./in.cue:11:13 + // t2.p1.d.a: cannot combine regular field "a" with 2: + // ./in.cue:11:11 + // t2.p1.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:11:8 + // ./in.cue:11:13 + // t2.p1.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:11:8 + // ./in.cue:11:11 + a: (struct){ + a: (_){ _ } + } + } + } + p2: (_|_){ + // [eval] + d: (_|_){ + // [eval] t2.p2.d: 7 errors in empty disjunction: // t2.p2.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): - // ./in.cue:14:5 // ./in.cue:15:8 // ./in.cue:15:13 // t2.p2.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): - // ./in.cue:14:5 - // ./in.cue:15:8 - // ./in.cue:15:11 - a: (struct){ - a: (int){ |((int){ 2 }, (int){ 1 }) } + // ./in.cue:15:8 + // ./in.cue:15:11 + // t2.p2.d.a: 4 errors in empty disjunction: + // t2.p2.d.a: cannot combine regular field "a" with 1: + // ./in.cue:15:13 + // t2.p2.d.a: cannot combine regular field "a" with 2: + // ./in.cue:15:11 + // t2.p2.d.a: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:15:8 + // ./in.cue:15:13 + // t2.p2.d.a: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): + // ./in.cue:15:8 + // ./in.cue:15:11 + a: (struct){ + a: (_){ _ } } } } @@ -118,10 +190,7 @@ } } issue3437: (struct){ - r: (_|_){ - // [incomplete] issue3437.r: cycle error referencing a: - // ./issue3437.cue:2:9 - } + r: (_){ _ } d: (struct){ a: (struct){ a: (struct){ @@ -131,33 +200,1293 @@ } } } - out: (struct){ - a: (struct){ - a: (struct){ |((struct){ - a: (struct){ - b: (int){ 4 } - } - b: (int){ 4 } - }, (struct){ - a: (struct){ - a: (struct){ - a: (struct){ |((struct){ - b: (int){ 4 } - }, (struct){ - a: (struct){ - a: (struct){ - a: (struct){ - b: (int){ 4 } - } - } - } - }) } - } - b: (int){ 4 } - } - }) } - } - b: (int){ 4 } - } + out: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + }) } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + } + }) } + }) } + }) } + }) } + }) } + }) } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + b: (int){ 4 } + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + b: (int){ 4 } + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + }) } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + b: (int){ 4 } + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + }) } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + b: (int){ 4 } + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + } + }) } + }) } + }) } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + b: (int){ 4 } + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + } + }) } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ |((struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + } + b: (int){ 4 } + } + }) } + b: (int){ 4 } + }, (struct){ + a: (struct){ |((struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + }, (struct){ + a: (struct){ + a: (struct){ + a: (struct){ + b: (int){ 4 } + } + b: (int){ 4 } + } + b: (int){ 4 } + } + }) } + }) } + }) } + }) } + }) } + }) } + }) } + }) } + }) } } } -- diff/todo/p2 -- Investigate differing counts of errors in empty disjunctions. This may indicate a performance issue. -- out/eval -- Errors: t1.p1: 2 errors in empty disjunction: t1.p1: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:2:2 ./in.cue:3:5 ./in.cue:3:10 t1.p1: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:2:2 ./in.cue:3:5 ./in.cue:3:8 t1.p2: 2 errors in empty disjunction: t1.p2: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:10 ./in.cue:7:2 t1.p2: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:6:5 ./in.cue:6:8 ./in.cue:7:2 t2.p1.d: 2 errors in empty disjunction: t2.p1.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:10:5 ./in.cue:11:8 ./in.cue:11:13 t2.p1.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:10:5 ./in.cue:11:8 ./in.cue:11:11 t2.p2.d: 2 errors in empty disjunction: t2.p2.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): ./in.cue:14:5 ./in.cue:15:8 ./in.cue:15:13 t2.p2.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): ./in.cue:14:5 ./in.cue:15:8 ./in.cue:15:11 Result: (_|_){ // [eval] t1: (_|_){ // [eval] p1: (_|_){ // [eval] t1.p1: 2 errors in empty disjunction: // t1.p1: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:2:2 // ./in.cue:3:5 // ./in.cue:3:10 // t1.p1: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:2:2 // ./in.cue:3:5 // ./in.cue:3:8 a: (struct){ a: (int){ |((int){ 2 }, (int){ 1 }) } } } p2: (_|_){ // [eval] t1.p2: 2 errors in empty disjunction: // t1.p2: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:10 // ./in.cue:7:2 // t1.p2: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:6:5 // ./in.cue:6:8 // ./in.cue:7:2 a: (struct){ a: (int){ |((int){ 2 }, (int){ 1 }) } } } } t2: (_|_){ // [eval] p1: (_|_){ // [eval] d: (_|_){ // [eval] t2.p1.d: 2 errors in empty disjunction: // t2.p1.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:10:5 // ./in.cue:11:8 // ./in.cue:11:13 // t2.p1.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:10:5 // ./in.cue:11:8 // ./in.cue:11:11 a: (struct){ a: (int){ |((int){ 2 }, (int){ 1 }) } } } } p2: (_|_){ // [eval] d: (_|_){ // [eval] t2.p2.d: 2 errors in empty disjunction: // t2.p2.d: conflicting values 1 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:14:5 // ./in.cue:15:8 // ./in.cue:15:13 // t2.p2.d: conflicting values 2 and {a:(2|1)} (mismatched types int and struct): // ./in.cue:14:5 // ./in.cue:15:8 // ./in.cue:15:11 a: (struct){ a: (int){ |((int){ 2 }, (int){ 1 }) } } } } } t3: (struct){ p1: (struct){ b: (int){ |((int){ 1 }, (int){ 2 }) } a: (int){ |((int){ 1 }, (int){ 2 }) } } p2: (struct){ b: (int){ |((int){ 1 }, (int){ 2 }) } a: (int){ |((int){ 1 }, (int){ 2 }) } } } issue3437: (struct){ r: (_|_){ // [incomplete] issue3437.r: cycle error referencing a: // ./issue3437.cue:2:9 } d: (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } } out: (struct){ a: (struct){ a: (struct){ |((struct){ a: (struct){ b: (int){ 4 } } b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ |((struct){ b: (int){ 4 } }, (struct){ a: (struct){ a: (struct){ a: (struct){ b: (int){ 4 } } } } }) } } b: (int){ 4 } } }) } } b: (int){ 4 } } } } cue-lang-cue-db9cc73/cue/testdata/eval/openinline.txtar000066400000000000000000000232561474664451600232500ustar00rootroot00000000000000#openInline: true -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- import ( pkg "foo.com/example" ) // This test tests that closeness errors are eliminated that occur within an // inline struct. inlineErr: { #D: {a: 1} // Allow a closedness error that occurs within an inline struct. def: x: (#D & {b: 2}).b } // These tests test that selecting into an inlined struct recursively opens this // struct in OpenInline. outerErr: { _inToOut: { in: _ out: in.foo } // The closedness of #Inner should be opened in OpenInline mode. issue3534: { #Inner: foo: minor: 2 #Outer: version: { major: 1, ... } t1: #Outer t1: version: (_inToOut & {in: #Inner}).out } // Test that the same principle works with the close builtin. usingClose: { // Same as above, but with an additional level of nesting. #Inner: foo: close({minor: 2}) #Outer: version: { major: 1, ... } t1: #Outer t1: version: (_inToOut & {in: #Inner}).out } // Test that the mechanism still works with extra nesting: the closedness of // #Inner should be opened recursively in OpenInline mode. extraNesting: { // Same as above, but with an additional level of nesting. #Inner: foo: x: minor: 2 #Outer: version: x: { major: 1, ... } t1: #Outer t1: version: (_inToOut & {in: #Inner}).out } } // Here OpenInline does _not_ erase the error, as the error is already present // in the referred definitions. // faulty struct referenced from package refFromPkg: (pkg.#E).b refFromLet: { let X = { #D: a: 2 #E: #D & {b: 1} } x: (X.#E).b } -- cue.mod/pkg/foo.com/example/example.cue -- package example #D: a: 1 #E: #D & {b: 1} -- out/eval/stats -- Leaks: 18 Freed: 73 Reused: 69 Allocs: 22 Retain: 37 Unifications: 91 Conjuncts: 141 Disjuncts: 107 -- out/evalalpha -- Errors: outerErr.usingClose.t1.version.major: field not allowed: ./in.cue:35:22 #E.b: field not allowed: ./in.cue:57:14 ./cue.mod/pkg/foo.com/example/example.cue:4:11 refFromLet.X.#E.b: field not allowed: ./in.cue:62:7 ./in.cue:62:13 Result: (_|_){ // [eval] inlineErr: (struct){ #D: (#struct){ a: (int){ 1 } } def: (struct){ x: (int){ 2 } } } outerErr: (_|_){ // [eval] _inToOut: (struct){ in: (_){ _ } out: (_|_){ // [incomplete] outerErr._inToOut.out: in.foo undefined as in is incomplete (type _): // ./in.cue:19:8 } } issue3534: (struct){ #Inner: (#struct){ foo: (#struct){ minor: (int){ 2 } } } #Outer: (#struct){ version: (#struct){ major: (int){ 1 } } } t1: (#struct){ version: (#struct){ major: (int){ 1 } minor: (int){ 2 } } } } usingClose: (_|_){ // [eval] #Inner: (#struct){ foo: (#struct){ minor: (int){ 2 } } } #Outer: (#struct){ version: (#struct){ major: (int){ 1 } } } t1: (_|_){ // [eval] version: (_|_){ // [eval] major: (_|_){ // [eval] outerErr.usingClose.t1.version.major: field not allowed: // ./in.cue:35:22 } minor: (int){ 2 } } } } extraNesting: (struct){ #Inner: (#struct){ foo: (#struct){ x: (#struct){ minor: (int){ 2 } } } } #Outer: (#struct){ version: (#struct){ x: (#struct){ major: (int){ 1 } } } } t1: (#struct){ version: (#struct){ x: (#struct){ major: (int){ 1 } minor: (int){ 2 } } } } } } refFromPkg: (_|_){ // [eval] #E.b: field not allowed: // ./in.cue:57:14 // ./cue.mod/pkg/foo.com/example/example.cue:4:11 } refFromLet: (_|_){ // [eval] let X#1 = (_|_){ // [eval] #D: (#struct){ a: (int){ 2 } } #E: (_|_){ // [eval] b: (_|_){ // [eval] refFromLet.X.#E.b: field not allowed: // ./in.cue:62:7 // ./in.cue:62:13 } a: (int){ 2 } } } x: (_|_){ // [eval] refFromLet.X.#E.b: field not allowed: // ./in.cue:62:7 // ./in.cue:62:13 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,10 +1,12 @@ Errors: outerErr.usingClose.t1.version.major: field not allowed: - ./in.cue:19:8 - ./in.cue:34:23 ./in.cue:35:22 - ./in.cue:37:7 - ./in.cue:38:16 +#E.b: field not allowed: + ./in.cue:57:14 + ./cue.mod/pkg/foo.com/example/example.cue:4:11 +refFromLet.X.#E.b: field not allowed: + ./in.cue:62:7 + ./in.cue:62:13 Result: (_|_){ @@ -62,11 +64,7 @@ // [eval] major: (_|_){ // [eval] outerErr.usingClose.t1.version.major: field not allowed: - // ./in.cue:19:8 - // ./in.cue:34:23 // ./in.cue:35:22 - // ./in.cue:37:7 - // ./in.cue:38:16 } minor: (int){ 2 } } @@ -97,8 +95,13 @@ } } } - refFromPkg: (int){ 1 } - refFromLet: (struct){ + refFromPkg: (_|_){ + // [eval] #E.b: field not allowed: + // ./in.cue:57:14 + // ./cue.mod/pkg/foo.com/example/example.cue:4:11 + } + refFromLet: (_|_){ + // [eval] let X#1 = (_|_){ // [eval] #D: (#struct){ @@ -106,15 +109,18 @@ } #E: (_|_){ // [eval] - a: (int){ 2 } b: (_|_){ // [eval] refFromLet.X.#E.b: field not allowed: - // ./in.cue:61:7 // ./in.cue:62:7 // ./in.cue:62:13 } - } - } - x: (int){ 1 } + a: (int){ 2 } + } + } + x: (_|_){ + // [eval] refFromLet.X.#E.b: field not allowed: + // ./in.cue:62:7 + // ./in.cue:62:13 + } } } -- out/eval -- Errors: outerErr.usingClose.t1.version.major: field not allowed: ./in.cue:19:8 ./in.cue:34:23 ./in.cue:35:22 ./in.cue:37:7 ./in.cue:38:16 Result: (_|_){ // [eval] inlineErr: (struct){ #D: (#struct){ a: (int){ 1 } } def: (struct){ x: (int){ 2 } } } outerErr: (_|_){ // [eval] _inToOut: (struct){ in: (_){ _ } out: (_|_){ // [incomplete] outerErr._inToOut.out: in.foo undefined as in is incomplete (type _): // ./in.cue:19:8 } } issue3534: (struct){ #Inner: (#struct){ foo: (#struct){ minor: (int){ 2 } } } #Outer: (#struct){ version: (#struct){ major: (int){ 1 } } } t1: (#struct){ version: (#struct){ major: (int){ 1 } minor: (int){ 2 } } } } usingClose: (_|_){ // [eval] #Inner: (#struct){ foo: (#struct){ minor: (int){ 2 } } } #Outer: (#struct){ version: (#struct){ major: (int){ 1 } } } t1: (_|_){ // [eval] version: (_|_){ // [eval] major: (_|_){ // [eval] outerErr.usingClose.t1.version.major: field not allowed: // ./in.cue:19:8 // ./in.cue:34:23 // ./in.cue:35:22 // ./in.cue:37:7 // ./in.cue:38:16 } minor: (int){ 2 } } } } extraNesting: (struct){ #Inner: (#struct){ foo: (#struct){ x: (#struct){ minor: (int){ 2 } } } } #Outer: (#struct){ version: (#struct){ x: (#struct){ major: (int){ 1 } } } } t1: (#struct){ version: (#struct){ x: (#struct){ major: (int){ 1 } minor: (int){ 2 } } } } } } refFromPkg: (int){ 1 } refFromLet: (struct){ let X#1 = (_|_){ // [eval] #D: (#struct){ a: (int){ 2 } } #E: (_|_){ // [eval] a: (int){ 2 } b: (_|_){ // [eval] refFromLet.X.#E.b: field not allowed: // ./in.cue:61:7 // ./in.cue:62:7 // ./in.cue:62:13 } } } x: (int){ 1 } } } -- out/compile -- --- in.cue { inlineErr: { #D: { a: 1 } def: { x: (〈1;#D〉 & { b: 2 }).b } } outerErr: { _inToOut: { in: _ out: 〈0;in〉.foo } issue3534: { #Inner: { foo: { minor: 2 } } #Outer: { version: { major: 1 ... } } t1: 〈0;#Outer〉 t1: { version: (〈2;_inToOut〉 & { in: 〈2;#Inner〉 }).out } } usingClose: { #Inner: { foo: close({ minor: 2 }) } #Outer: { version: { major: 1 ... } } t1: 〈0;#Outer〉 t1: { version: (〈2;_inToOut〉 & { in: 〈2;#Inner〉 }).out } } extraNesting: { #Inner: { foo: { x: { minor: 2 } } } #Outer: { version: { x: { major: 1 ... } } } t1: 〈0;#Outer〉 t1: { version: (〈2;_inToOut〉 & { in: 〈2;#Inner〉 }).out } } } refFromPkg: 〈import;"foo.com/example"〉.#E.b refFromLet: { let X#1 = { #D: { a: 2 } #E: (〈0;#D〉 & { b: 1 }) } x: 〈0;let X#1〉.#E.b } } cue-lang-cue-db9cc73/cue/testdata/eval/required.txtar000066400000000000000000000161521474664451600227250ustar00rootroot00000000000000-- in.cue -- self: t1: { a?: int } self: t2: { a!: int a!: int } unify: t1: p1: { a!: int a: int } unify: t1: p2: { a: int a!: int } unify: t2: p1: { a!: int a?: int } unify: t2: p2: { a?: int a!: int } #Def: t1: { a!: int } allowed: issue2306: { #A: a!: int #A: #B #B: b!: int } reference: { toWithinDefinition: p1:{ #Foo: a!: int b: #Foo.a } toWithinDefinition: p2:{ b: #Foo.a #Foo: a!: int } toFieldFromDefinition: p1: { #Foo: a!: int b: #Foo c: b.a } toFieldFromDefinition: p2: { c: b.a b: #Foo #Foo: a!: int } toNonDefinition: p1: { x: y!: _ b: x.y } toNonDefinition: p2: { b: x.y x: y!: _ } toConcrete: p1: { a!: 1 b: a + 1 } toConcrete: p2: { b: a + 1 a!: 1 } } -- out/compile -- --- in.cue { self: { t1: { a?: int } } self: { t2: { a!: int a!: int } } unify: { t1: { p1: { a!: int a: int } } } unify: { t1: { p2: { a: int a!: int } } } unify: { t2: { p1: { a!: int a?: int } } } unify: { t2: { p2: { a?: int a!: int } } } #Def: { t1: { a!: int } } allowed: { issue2306: { #A: { a!: int } #A: 〈0;#B〉 #B: { b!: int } } } reference: { toWithinDefinition: { p1: { #Foo: { a!: int } b: 〈0;#Foo〉.a } } toWithinDefinition: { p2: { b: 〈0;#Foo〉.a #Foo: { a!: int } } } toFieldFromDefinition: { p1: { #Foo: { a!: int } b: 〈0;#Foo〉 c: 〈0;b〉.a } } toFieldFromDefinition: { p2: { c: 〈0;b〉.a b: 〈0;#Foo〉 #Foo: { a!: int } } } toNonDefinition: { p1: { x: { y!: _ } b: 〈0;x〉.y } } toNonDefinition: { p2: { b: 〈0;x〉.y x: { y!: _ } } } toConcrete: { p1: { a!: 1 b: (〈0;a〉 + 1) } } toConcrete: { p2: { b: (〈0;a〉 + 1) a!: 1 } } } } -- out/eval/stats -- Leaks: 0 Freed: 66 Reused: 58 Allocs: 8 Retain: 10 Unifications: 66 Conjuncts: 90 Disjuncts: 76 -- out/evalalpha -- (_|_){ // [eval] self: (struct){ t1: (struct){ a?: (int){ int } } t2: (struct){ a!: (int){ int } } } unify: (struct){ t1: (struct){ p1: (struct){ a: (int){ int } } p2: (struct){ a: (int){ int } } } t2: (struct){ p1: (struct){ a!: (int){ int } } p2: (struct){ a!: (int){ int } } } } #Def: (#struct){ t1: (#struct){ a!: (int){ int } } } allowed: (_|_){ // [eval] issue2306: (_|_){ // [eval] #A: (_|_){ // [eval] a!: (_|_){ // [eval] allowed.issue2306.#A.a: field not allowed: // ./in.cue:34:6 } b!: (int){ int } } #B: (#struct){ b!: (int){ int } } } } reference: (struct){ toWithinDefinition: (struct){ p1: (struct){ #Foo: (#struct){ a!: (int){ int } } b: (int){ int } } p2: (struct){ b: (int){ int } #Foo: (#struct){ a!: (int){ int } } } } toFieldFromDefinition: (struct){ p1: (struct){ #Foo: (#struct){ a!: (int){ int } } b: ~(reference.toFieldFromDefinition.p1.#Foo) c: (int){ int } } p2: (struct){ c: (int){ int } b: ~(reference.toFieldFromDefinition.p2.#Foo) #Foo: (#struct){ a!: (int){ int } } } } toNonDefinition: (struct){ p1: (struct){ x: (struct){ y!: (_){ _ } } b: (_){ _ } } p2: (struct){ b: (_){ _ } x: (struct){ y!: (_){ _ } } } } toConcrete: (struct){ p1: (struct){ a!: (int){ 1 } b: (int){ 2 } } p2: (struct){ b: (int){ 2 } a!: (int){ 1 } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -40,8 +40,6 @@ a!: (_|_){ // [eval] allowed.issue2306.#A.a: field not allowed: // ./in.cue:34:6 - // ./in.cue:35:6 - // ./in.cue:37:6 } b!: (int){ int } } @@ -70,16 +68,12 @@ #Foo: (#struct){ a!: (int){ int } } - b: (#struct){ - a!: (int){ int } - } - c: (int){ int } - } - p2: (struct){ - c: (int){ int } - b: (#struct){ - a!: (int){ int } - } + b: ~(reference.toFieldFromDefinition.p1.#Foo) + c: (int){ int } + } + p2: (struct){ + c: (int){ int } + b: ~(reference.toFieldFromDefinition.p2.#Foo) #Foo: (#struct){ a!: (int){ int } } -- diff/todo/p2 -- Missing position. -- out/eval -- (_|_){ // [eval] self: (struct){ t1: (struct){ a?: (int){ int } } t2: (struct){ a!: (int){ int } } } unify: (struct){ t1: (struct){ p1: (struct){ a: (int){ int } } p2: (struct){ a: (int){ int } } } t2: (struct){ p1: (struct){ a!: (int){ int } } p2: (struct){ a!: (int){ int } } } } #Def: (#struct){ t1: (#struct){ a!: (int){ int } } } allowed: (_|_){ // [eval] issue2306: (_|_){ // [eval] #A: (_|_){ // [eval] a!: (_|_){ // [eval] allowed.issue2306.#A.a: field not allowed: // ./in.cue:34:6 // ./in.cue:35:6 // ./in.cue:37:6 } b!: (int){ int } } #B: (#struct){ b!: (int){ int } } } } reference: (struct){ toWithinDefinition: (struct){ p1: (struct){ #Foo: (#struct){ a!: (int){ int } } b: (int){ int } } p2: (struct){ b: (int){ int } #Foo: (#struct){ a!: (int){ int } } } } toFieldFromDefinition: (struct){ p1: (struct){ #Foo: (#struct){ a!: (int){ int } } b: (#struct){ a!: (int){ int } } c: (int){ int } } p2: (struct){ c: (int){ int } b: (#struct){ a!: (int){ int } } #Foo: (#struct){ a!: (int){ int } } } } toNonDefinition: (struct){ p1: (struct){ x: (struct){ y!: (_){ _ } } b: (_){ _ } } p2: (struct){ b: (_){ _ } x: (struct){ y!: (_){ _ } } } } toConcrete: (struct){ p1: (struct){ a!: (int){ 1 } b: (int){ 2 } } p2: (struct){ b: (int){ 2 } a!: (int){ 1 } } } } } cue-lang-cue-db9cc73/cue/testdata/eval/resolve_basic.txtar000066400000000000000000000011541474664451600237210ustar00rootroot00000000000000-- in.cue -- a: 1 b: a + 1 d: { x: _ y: b + x } e: d & { x: 5 } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 6 Allocs: 3 Retain: 0 Unifications: 9 Conjuncts: 16 Disjuncts: 9 -- out/eval -- (struct){ a: (int){ 1 } b: (int){ 2 } d: (struct){ x: (_){ _ } y: (_|_){ // [incomplete] d.y: non-concrete value _ in operand to +: // ./in.cue:5:5 // ./in.cue:4:5 } } e: (struct){ x: (int){ 5 } y: (int){ 7 } } } -- out/compile -- --- in.cue { a: 1 b: (〈0;a〉 + 1) d: { x: _ y: (〈1;b〉 + 〈0;x〉) } e: (〈0;d〉 & { x: 5 }) } cue-lang-cue-db9cc73/cue/testdata/eval/resolve_env.txtar000066400000000000000000000015541474664451600234340ustar00rootroot00000000000000-- in.cue -- a: { d: int b: { c: d } } x: { d: 2 b: a.b.c // should be int, not 2 } a1: y: 5 a1: a2: a3: a4: a5: a1.y b: a1.a2.a3.a4.a5 -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 9 Allocs: 6 Retain: 0 Unifications: 15 Conjuncts: 22 Disjuncts: 15 -- out/eval -- (struct){ a: (struct){ d: (int){ int } b: (struct){ c: (int){ int } } } x: (struct){ d: (int){ 2 } b: (int){ int } } a1: (struct){ y: (int){ 5 } a2: (struct){ a3: (struct){ a4: (struct){ a5: (int){ 5 } } } } } b: (int){ 5 } } -- out/compile -- --- in.cue { a: { d: int b: { c: 〈1;d〉 } } x: { d: 2 b: 〈1;a〉.b.c } a1: { y: 5 } a1: { a2: { a3: { a4: { a5: 〈4;a1〉.y } } } } b: 〈0;a1〉.a2.a3.a4.a5 } cue-lang-cue-db9cc73/cue/testdata/eval/selectors.txtar000066400000000000000000000020711474664451600231030ustar00rootroot00000000000000-- in.cue -- a: 1 b: a + 1 d: { x: _ y: b + x } e: d & { x: 5 } f: { a: "foo-bar": 3 b: a."foo-bar" } g: { a: "foo-bar": c: 3 b: a."foo-bar".c } -- out/eval/stats -- Leaks: 0 Freed: 18 Reused: 13 Allocs: 5 Retain: 0 Unifications: 18 Conjuncts: 27 Disjuncts: 18 -- out/eval -- (struct){ a: (int){ 1 } b: (int){ 2 } d: (struct){ x: (_){ _ } y: (_|_){ // [incomplete] d.y: non-concrete value _ in operand to +: // ./in.cue:5:5 // ./in.cue:4:5 } } e: (struct){ x: (int){ 5 } y: (int){ 7 } } f: (struct){ a: (struct){ "foo-bar": (int){ 3 } } b: (int){ 3 } } g: (struct){ a: (struct){ "foo-bar": (struct){ c: (int){ 3 } } } b: (int){ 3 } } } -- out/compile -- --- in.cue { a: 1 b: (〈0;a〉 + 1) d: { x: _ y: (〈1;b〉 + 〈0;x〉) } e: (〈0;d〉 & { x: 5 }) f: { a: { "foo-bar": 3 } b: 〈0;a〉."foo-bar" } g: { a: { "foo-bar": { c: 3 } } b: 〈0;a〉."foo-bar".c } } cue-lang-cue-db9cc73/cue/testdata/eval/sharing.txtar000066400000000000000000000626741474664451600225520ustar00rootroot00000000000000 -- in.cue -- issue3062: ok1: { #S: "a" #o: x: #S o: #o o: X X: x: A A: "a" } issue3601: ok1: { Y: (X & __no_sharing).a X: a: b: a.b out: Y & __no_sharing } // Test debug facilities to turn of sharing. debug: { sharingOn: { a: b b: c: 1 } sharingOff: t1: { a: b & __no_sharing b: c: 1 } sharingOff: t2: { a: b a: __no_sharing b: c: 1 } sharingOff: t3: { a: __no_sharing a: b b: c: 1 } } -- dupshare.cue -- // This file contains tests where unifying the same field multiple times into // a field with different "closedness" history should compute closedness // correctly. issue3641: simplified: t1: { #Context1: ctx: {} Context2: ctx: {} // Must both refer to #Context1 #Config1: cfg: #Context1 #Config3: cfg: #Context1 Config2: cfg: Context2 Config: #Config1 & Config2 // order matters out: Config // Indirection necessary. out: #Config3 } issue3641: simplified: t2: { #Context1: ctx: {} Context2: ctx: {} // Must both refer to #Context1 #Config1: cfg: #Context1 #Config3: cfg: #Context1 Config2: cfg: Context2 Config: #Config1 & Config2 // order matters out: Config // Indirection necessary. out: #Config3 } // Variant where sharing is explicitly disabled. issue3641: simplified: t3: { #Context1: ctx: {} Context2: ctx: {} // Must both refer to #Context1 #Config1: cfg: #Context1 #Config3: cfg: #Context1 Config2: cfg: Context2 Config: #Config1 & Config2 // order matters out: __no_sharing out: Config // Indirection necessary. out: #Config3 } issue3641: full: { #Context1: ctx: {} #Context2: ctx: {} #Config1: cfg: #Context1 #Config2: cfg: #Context2 #Schema: sch: #Config1 #Config: #Config1 & #Config2 let config = #Config out: #Schema & { sch: config } } issue3546: reduced: { all: ["a"] #all: all #Network: list: #List #List: [...string] val: #Network val: list: #all out: #Network out: val } -- sharecycle.cue -- shareCycle: t1: { #X: {} Y: { x: #X & Y } } shareCycle: t2: { #X: int Y: { x: #X & Y } } shareCycle: t3: { #X: {} Y: { x: Y & #X } } -- acrossdisjunction.cue -- import "list" issue3679: { // The result of list.Repeat is structure shared in env. This needs to be // "unshared" within the disjunction. Ensure that unsharing a shared Vertex // works arcross disjunction boundaries. b: null | [string] b: list.Repeat([for k, v in [0] { "bar" }], 1) } -- out/eval/stats -- Leaks: 3 Freed: 172 Reused: 165 Allocs: 10 Retain: 21 Unifications: 173 Conjuncts: 361 Disjuncts: 191 -- out/evalalpha -- Errors: shareCycle.t2.Y.x: conflicting values int and {x:(#X & Y)} (mismatched types int and struct): ./sharecycle.cue:8:6 ./sharecycle.cue:9:5 shareCycle.t1.Y.x.x: field not allowed: ./sharecycle.cue:4:11 ./sharecycle.cue:4:3 shareCycle.t2.Y.x.x: field not allowed: ./sharecycle.cue:10:11 ./sharecycle.cue:10:3 shareCycle.t3.Y.x.x: field not allowed: ./sharecycle.cue:16:10 ./sharecycle.cue:16:3 Result: (_|_){ // [eval] issue3679: (struct){ b: (#list){ 0: (string){ "bar" } } } issue3641: (struct){ simplified: (struct){ t1: (struct){ #Context1: (#struct){ ctx: (#struct){ } } Context2: (struct){ ctx: (struct){ } } #Config1: (#struct){ cfg: ~(issue3641.simplified.t1.#Context1) } #Config3: (#struct){ cfg: ~(issue3641.simplified.t1.#Context1) } Config2: (struct){ cfg: ~(issue3641.simplified.t1.Context2) } Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } t2: (struct){ #Context1: (#struct){ ctx: (#struct){ } } Context2: (struct){ ctx: (struct){ } } #Config1: (#struct){ cfg: ~(issue3641.simplified.t2.#Context1) } #Config3: (#struct){ cfg: ~(issue3641.simplified.t2.#Context1) } Config2: (struct){ cfg: ~(issue3641.simplified.t2.Context2) } Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } t3: (struct){ #Context1: (#struct){ ctx: (#struct){ } } Context2: (struct){ ctx: (struct){ } } #Config1: (#struct){ cfg: ~(issue3641.simplified.t3.#Context1) } #Config3: (#struct){ cfg: ~(issue3641.simplified.t3.#Context1) } Config2: (struct){ cfg: ~(issue3641.simplified.t3.Context2) } Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } } full: (struct){ #Context1: (#struct){ ctx: (#struct){ } } #Context2: (#struct){ ctx: (#struct){ } } #Config1: (#struct){ cfg: ~(issue3641.full.#Context1) } #Config2: (#struct){ cfg: ~(issue3641.full.#Context2) } #Schema: (#struct){ sch: ~(issue3641.full.#Config1) } #Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } let config#1 = ~(issue3641.full.#Config) out: (#struct){ sch: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } } } issue3546: (struct){ reduced: (struct){ all: (#list){ 0: (string){ "a" } } #all: (#list){ 0: (string){ "a" } } #Network: (#struct){ list: (list){ } } #List: (list){ } val: (#struct){ list: (#list){ 0: (string){ "a" } } } out: (#struct){ list: (#list){ 0: (string){ "a" } } } } } issue3062: (struct){ ok1: (struct){ #S: (string){ "a" } #o: (#struct){ x: (string){ "a" } } o: (#struct){ x: (string){ "a" } } X: (struct){ x: (string){ "a" } } A: (string){ "a" } } } issue3601: (struct){ ok1: (struct){ Y: (struct){ b: (_){ _ } } X: (struct){ a: (struct){ b: (_){ _ } } } out: (struct){ b: (_){ _ } } } } debug: (struct){ sharingOn: (struct){ a: ~(debug.sharingOn.b) b: (struct){ c: (int){ 1 } } } sharingOff: (struct){ t1: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t2: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t3: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } } } shareCycle: (_|_){ // [eval] t1: (_|_){ // [eval] #X: (#struct){ } Y: (_|_){ // [eval] x: (_|_){ // [eval] x: (_|_){ // [eval] shareCycle.t1.Y.x.x: field not allowed: // ./sharecycle.cue:4:11 // ./sharecycle.cue:4:3 } } } } t2: (_|_){ // [eval] #X: (int){ int } Y: (_|_){ // [eval] x: (_|_){ // [eval] shareCycle.t2.Y.x: conflicting values int and {x:(#X & Y)} (mismatched types int and struct): // ./sharecycle.cue:8:6 // ./sharecycle.cue:9:5 // shareCycle.t2.Y.x.x: field not allowed: // ./sharecycle.cue:10:11 // ./sharecycle.cue:10:3 x: (_|_){ // [eval] shareCycle.t2.Y.x.x: field not allowed: // ./sharecycle.cue:10:11 // ./sharecycle.cue:10:3 } } } } t3: (_|_){ // [eval] #X: (#struct){ } Y: (_|_){ // [eval] x: (_|_){ // [eval] x: (_|_){ // [eval] shareCycle.t3.Y.x.x: field not allowed: // ./sharecycle.cue:16:10 // ./sharecycle.cue:16:3 } } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,11 +1,16 @@ Errors: -shareCycle.t1.Y.x.x: structural cycle shareCycle.t2.Y.x: conflicting values int and {x:(#X & Y)} (mismatched types int and struct): ./sharecycle.cue:8:6 ./sharecycle.cue:9:5 +shareCycle.t1.Y.x.x: field not allowed: + ./sharecycle.cue:4:11 + ./sharecycle.cue:4:3 +shareCycle.t2.Y.x.x: field not allowed: ./sharecycle.cue:10:11 -shareCycle.t2.Y.x.x: structural cycle -shareCycle.t3.Y.x.x: structural cycle + ./sharecycle.cue:10:3 +shareCycle.t3.Y.x.x: field not allowed: + ./sharecycle.cue:16:10 + ./sharecycle.cue:16:3 Result: (_|_){ @@ -27,102 +32,75 @@ } } #Config1: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - #Config3: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - Config2: (struct){ - cfg: (struct){ - ctx: (struct){ - } - } - } - Config: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - out: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - } - t2: (struct){ - #Context1: (#struct){ - ctx: (#struct){ - } - } - Context2: (struct){ - ctx: (struct){ - } - } - #Config1: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - #Config3: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - Config2: (struct){ - cfg: (struct){ - ctx: (struct){ - } - } - } - Config: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - out: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - } - t3: (struct){ - #Context1: (#struct){ - ctx: (#struct){ - } - } - Context2: (struct){ - ctx: (struct){ - } - } - #Config1: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - #Config3: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } - Config2: (struct){ - cfg: (struct){ - ctx: (struct){ - } - } + cfg: ~(issue3641.simplified.t1.#Context1) + } + #Config3: (#struct){ + cfg: ~(issue3641.simplified.t1.#Context1) + } + Config2: (struct){ + cfg: ~(issue3641.simplified.t1.Context2) + } + Config: (#struct){ + cfg: (#struct){ + ctx: (#struct){ + } + } + } + out: (#struct){ + cfg: (#struct){ + ctx: (#struct){ + } + } + } + } + t2: (struct){ + #Context1: (#struct){ + ctx: (#struct){ + } + } + Context2: (struct){ + ctx: (struct){ + } + } + #Config1: (#struct){ + cfg: ~(issue3641.simplified.t2.#Context1) + } + #Config3: (#struct){ + cfg: ~(issue3641.simplified.t2.#Context1) + } + Config2: (struct){ + cfg: ~(issue3641.simplified.t2.Context2) + } + Config: (#struct){ + cfg: (#struct){ + ctx: (#struct){ + } + } + } + out: (#struct){ + cfg: (#struct){ + ctx: (#struct){ + } + } + } + } + t3: (struct){ + #Context1: (#struct){ + ctx: (#struct){ + } + } + Context2: (struct){ + ctx: (struct){ + } + } + #Config1: (#struct){ + cfg: ~(issue3641.simplified.t3.#Context1) + } + #Config3: (#struct){ + cfg: ~(issue3641.simplified.t3.#Context1) + } + Config2: (struct){ + cfg: ~(issue3641.simplified.t3.Context2) } Config: (#struct){ cfg: (#struct){ @@ -148,24 +126,13 @@ } } #Config1: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } + cfg: ~(issue3641.full.#Context1) } #Config2: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } + cfg: ~(issue3641.full.#Context2) } #Schema: (#struct){ - sch: (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } + sch: ~(issue3641.full.#Config1) } #Config: (#struct){ cfg: (#struct){ @@ -173,12 +140,7 @@ } } } - let config#1 = (#struct){ - cfg: (#struct){ - ctx: (#struct){ - } - } - } + let config#1 = ~(issue3641.full.#Config) out: (#struct){ sch: (#struct){ cfg: (#struct){ @@ -247,9 +209,7 @@ } debug: (struct){ sharingOn: (struct){ - a: (struct){ - c: (int){ 1 } - } + a: ~(debug.sharingOn.b) b: (struct){ c: (int){ 1 } } @@ -284,15 +244,17 @@ shareCycle: (_|_){ // [eval] t1: (_|_){ - // [structural cycle] - #X: (#struct){ - } - Y: (_|_){ - // [structural cycle] - x: (_|_){ - // [structural cycle] - x: (_|_){ - // [structural cycle] shareCycle.t1.Y.x.x: structural cycle + // [eval] + #X: (#struct){ + } + Y: (_|_){ + // [eval] + x: (_|_){ + // [eval] + x: (_|_){ + // [eval] shareCycle.t1.Y.x.x: field not allowed: + // ./sharecycle.cue:4:11 + // ./sharecycle.cue:4:3 } } } @@ -306,23 +268,29 @@ // [eval] shareCycle.t2.Y.x: conflicting values int and {x:(#X & Y)} (mismatched types int and struct): // ./sharecycle.cue:8:6 // ./sharecycle.cue:9:5 + // shareCycle.t2.Y.x.x: field not allowed: // ./sharecycle.cue:10:11 - x: (_|_){ - // [structural cycle] shareCycle.t2.Y.x.x: structural cycle + // ./sharecycle.cue:10:3 + x: (_|_){ + // [eval] shareCycle.t2.Y.x.x: field not allowed: + // ./sharecycle.cue:10:11 + // ./sharecycle.cue:10:3 } } } } t3: (_|_){ - // [structural cycle] - #X: (#struct){ - } - Y: (_|_){ - // [structural cycle] - x: (_|_){ - // [structural cycle] - x: (_|_){ - // [structural cycle] shareCycle.t3.Y.x.x: structural cycle + // [eval] + #X: (#struct){ + } + Y: (_|_){ + // [eval] + x: (_|_){ + // [eval] + x: (_|_){ + // [eval] shareCycle.t3.Y.x.x: field not allowed: + // ./sharecycle.cue:16:10 + // ./sharecycle.cue:16:3 } } } -- out/eval -- Errors: shareCycle.t1.Y.x.x: structural cycle shareCycle.t2.Y.x: conflicting values int and {x:(#X & Y)} (mismatched types int and struct): ./sharecycle.cue:8:6 ./sharecycle.cue:9:5 ./sharecycle.cue:10:11 shareCycle.t2.Y.x.x: structural cycle shareCycle.t3.Y.x.x: structural cycle Result: (_|_){ // [eval] issue3679: (struct){ b: (#list){ 0: (string){ "bar" } } } issue3641: (struct){ simplified: (struct){ t1: (struct){ #Context1: (#struct){ ctx: (#struct){ } } Context2: (struct){ ctx: (struct){ } } #Config1: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } #Config3: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } Config2: (struct){ cfg: (struct){ ctx: (struct){ } } } Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } t2: (struct){ #Context1: (#struct){ ctx: (#struct){ } } Context2: (struct){ ctx: (struct){ } } #Config1: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } #Config3: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } Config2: (struct){ cfg: (struct){ ctx: (struct){ } } } Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } t3: (struct){ #Context1: (#struct){ ctx: (#struct){ } } Context2: (struct){ ctx: (struct){ } } #Config1: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } #Config3: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } Config2: (struct){ cfg: (struct){ ctx: (struct){ } } } Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } } full: (struct){ #Context1: (#struct){ ctx: (#struct){ } } #Context2: (#struct){ ctx: (#struct){ } } #Config1: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } #Config2: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } #Schema: (#struct){ sch: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } #Config: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } let config#1 = (#struct){ cfg: (#struct){ ctx: (#struct){ } } } out: (#struct){ sch: (#struct){ cfg: (#struct){ ctx: (#struct){ } } } } } } issue3546: (struct){ reduced: (struct){ all: (#list){ 0: (string){ "a" } } #all: (#list){ 0: (string){ "a" } } #Network: (#struct){ list: (list){ } } #List: (list){ } val: (#struct){ list: (#list){ 0: (string){ "a" } } } out: (#struct){ list: (#list){ 0: (string){ "a" } } } } } issue3062: (struct){ ok1: (struct){ #S: (string){ "a" } #o: (#struct){ x: (string){ "a" } } o: (#struct){ x: (string){ "a" } } X: (struct){ x: (string){ "a" } } A: (string){ "a" } } } issue3601: (struct){ ok1: (struct){ Y: (struct){ b: (_){ _ } } X: (struct){ a: (struct){ b: (_){ _ } } } out: (struct){ b: (_){ _ } } } } debug: (struct){ sharingOn: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } sharingOff: (struct){ t1: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t2: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } t3: (struct){ a: (struct){ c: (int){ 1 } } b: (struct){ c: (int){ 1 } } } } } shareCycle: (_|_){ // [eval] t1: (_|_){ // [structural cycle] #X: (#struct){ } Y: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] shareCycle.t1.Y.x.x: structural cycle } } } } t2: (_|_){ // [eval] #X: (int){ int } Y: (_|_){ // [eval] x: (_|_){ // [eval] shareCycle.t2.Y.x: conflicting values int and {x:(#X & Y)} (mismatched types int and struct): // ./sharecycle.cue:8:6 // ./sharecycle.cue:9:5 // ./sharecycle.cue:10:11 x: (_|_){ // [structural cycle] shareCycle.t2.Y.x.x: structural cycle } } } } t3: (_|_){ // [structural cycle] #X: (#struct){ } Y: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] x: (_|_){ // [structural cycle] shareCycle.t3.Y.x.x: structural cycle } } } } } } -- out/compile -- --- acrossdisjunction.cue { issue3679: { b: (null|[ string, ]) b: 〈import;list〉.Repeat([ for k, v in [ 0, ] { "bar" }, ], 1) } } --- dupshare.cue { issue3641: { simplified: { t1: { #Context1: { ctx: {} } Context2: { ctx: {} } #Config1: { cfg: 〈1;#Context1〉 } #Config3: { cfg: 〈1;#Context1〉 } Config2: { cfg: 〈1;Context2〉 } Config: (〈0;#Config1〉 & 〈0;Config2〉) out: 〈0;Config〉 out: 〈0;#Config3〉 } } } issue3641: { simplified: { t2: { #Context1: { ctx: {} } Context2: { ctx: {} } #Config1: { cfg: 〈1;#Context1〉 } #Config3: { cfg: 〈1;#Context1〉 } Config2: { cfg: 〈1;Context2〉 } Config: (〈0;#Config1〉 & 〈0;Config2〉) out: 〈0;Config〉 out: 〈0;#Config3〉 } } } issue3641: { simplified: { t3: { #Context1: { ctx: {} } Context2: { ctx: {} } #Config1: { cfg: 〈1;#Context1〉 } #Config3: { cfg: 〈1;#Context1〉 } Config2: { cfg: 〈1;Context2〉 } Config: (〈0;#Config1〉 & 〈0;Config2〉) out: _|_(no sharing) out: 〈0;Config〉 out: 〈0;#Config3〉 } } } issue3641: { full: { #Context1: { ctx: {} } #Context2: { ctx: {} } #Config1: { cfg: 〈1;#Context1〉 } #Config2: { cfg: 〈1;#Context2〉 } #Schema: { sch: 〈1;#Config1〉 } #Config: (〈0;#Config1〉 & 〈0;#Config2〉) let config#1 = 〈0;#Config〉 out: (〈0;#Schema〉 & { sch: 〈1;let config#1〉 }) } } issue3546: { reduced: { all: [ "a", ] #all: 〈0;all〉 #Network: { list: 〈1;#List〉 } #List: [ ...string, ] val: 〈0;#Network〉 val: { list: 〈1;#all〉 } out: 〈0;#Network〉 out: 〈0;val〉 } } } --- in.cue { issue3062: { ok1: { #S: "a" #o: { x: 〈1;#S〉 } o: 〈0;#o〉 o: 〈0;X〉 X: { x: 〈1;A〉 } A: "a" } } issue3601: { ok1: { Y: (〈0;X〉 & _|_(no sharing)).a X: { a: { b: 〈1;a〉.b } } out: (〈0;Y〉 & _|_(no sharing)) } } debug: { sharingOn: { a: 〈0;b〉 b: { c: 1 } } sharingOff: { t1: { a: (〈0;b〉 & _|_(no sharing)) b: { c: 1 } } } sharingOff: { t2: { a: 〈0;b〉 a: _|_(no sharing) b: { c: 1 } } } sharingOff: { t3: { a: _|_(no sharing) a: 〈0;b〉 b: { c: 1 } } } } } --- sharecycle.cue { shareCycle: { t1: { #X: {} Y: { x: (〈1;#X〉 & 〈1;Y〉) } } } shareCycle: { t2: { #X: int Y: { x: (〈1;#X〉 & 〈1;Y〉) } } } shareCycle: { t3: { #X: {} Y: { x: (〈1;Y〉 & 〈1;#X〉) } } } } cue-lang-cue-db9cc73/cue/testdata/eval/structs.txtar000066400000000000000000000005041474664451600226060ustar00rootroot00000000000000-- in.cue -- import "struct" v: {a: struct.MaxFields(2) & {}}.a -- out/eval/stats -- Leaks: 2 Freed: 2 Reused: 0 Allocs: 4 Retain: 2 Unifications: 4 Conjuncts: 7 Disjuncts: 4 -- out/eval -- (struct){ v: (struct){ } } -- out/compile -- --- in.cue { v: { a: (〈import;struct〉.MaxFields(2) & {}) }.a } cue-lang-cue-db9cc73/cue/testdata/eval/unify.txtar000066400000000000000000000013071474664451600222330ustar00rootroot00000000000000-- in.cue -- a: d: { #base #info: {...} Y: #info.X } #base: { #info: {...} } a: [Name=string]: {#info: { X: "foo" }} -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 3 Allocs: 5 Retain: 1 Unifications: 8 Conjuncts: 19 Disjuncts: 9 -- out/eval -- (struct){ a: (struct){ d: (#struct){ #info: (#struct){ X: (string){ "foo" } } Y: (string){ "foo" } } } #base: (#struct){ #info: (#struct){ } } } -- out/compile -- --- in.cue { a: { d: { 〈2;#base〉 #info: { ... } Y: 〈0;#info〉.X } } #base: { #info: { ... } } a: { [string]: { #info: { X: "foo" } } } } cue-lang-cue-db9cc73/cue/testdata/eval/v0.7.txtar000066400000000000000000001123341474664451600215760ustar00rootroot00000000000000# Some new cases specific to v0.7 -- builtins.cue -- import "strings" mutualBuiltin: t1: ok: { // Results in incomplete error in v0.6 s3: strings.ContainsAny(s4) s4: strings.ContainsAny(s3) s4: "dd" } mutualBuiltin: t2: ok: { s3: strings.ContainsAny(s5, "dd") s5: s6 s6: "dd" } -- comprehensions.cue -- comprehensions: t1: ok: { src: ["foo"] for v in src { "\(v)": v } } -- dynamic.cue -- dynamic: t1: ok: { [X=string]: {name: X} (x.y): {} x: y: "foo" } dynamic: t2: ok: { foo: #X #X: { a: b: C: 1 for _ in a { a: ("b"): D: 2 } } } -- definition.cue -- definition: t0: err: { #D1: env: {} d1: env: c: "C" d1: #D1 } definition: t1: err: { a: #A a: c: 1 // defining after first reference triggers notification mechanism to kick in. #A: {} } definition: t2: ok: p1: { #A: { ... {a: int} } x: #A & { c: int } } definition: t2: ok: p2: { #A: { {a: int} ... } x: #A & { c: int } } definition: t2: ok: p3: { x: #A & { c: int } #A: { ... {a: int} } } definition: t2: ok: p4: { x: #A & { c: int } #A: { {a: int} ... } } -- expr.cue -- expr: t1: ok: { a: X X: 5.0 X: Y / 2 Y: a * 2 } expr: t2: ok: { A: X + 2 X: 5 X: A - 2 } expr: t3: ok: p1: { a0: X X: 5.0 X: a0 * 1 } expr: t3: ok: p2: { b: Y * 1 Y: b * 1 Y: 5.0 } expr: t4: ok: { // -> a0 -> X -> b1 -> b0 -> a1 -> a0 a0: X // Need all conjuncts known from X b0: a1 a1: a0 + 2 b1: b0 - 2 a0: X X: b1 X: 5.0 } -- in.cue -- mutual: t0: ok: { c: e & {b: 2} e: {a: 1} e: c } mutual: t1: ok: { a: { b b: {b: f: 1} } a: a.b a: b: {b: f: 1} } mutual: t2: ok: { x: a: a: f: 1 x: y.a y: a: a: e: 1 y: x.a } mutual: t3: ok: { d: e: f: 1 d d: d: e: g: 1 } // This test fails for some permutations in v0.6. mutual: t4: ok: { p0: { z: x.b x: b: y.c x: b: {d: b: 2} y: c: z.d z: d: {a: 1} } p1: { x: b: y.c z: x.b x: b: {d: b: 2} y: c: z.d z: d: {a: 1} } p2: { x: b: y.c x: b: {d: b: 2} y: c: z.d z: x.b z: d: {a: 1} } p3: { x: b: {d: b: 2} y: c: z.d z: x.b x: b: y.c z: d: {a: 1} } p4: { z: x.b x: b: {d: b: 2} y: c: z.d x: b: y.c z: d: {a: 1} } p5: { x: b: {d: b: 2} y: c: z.d x: b: y.c z: x.b z: d: {a: 1} } check: p1 & p2 & p3 & p4 & p5 } -- equality.cue -- issue3194: reduced: { A: *0 | >10 A: *0 | >10 { out: close({ b: A }) out: b: A }.out } -- out/eval/stats -- Leaks: 4 Freed: 285 Reused: 273 Allocs: 16 Retain: 170 Unifications: 269 Conjuncts: 1619 Disjuncts: 436 -- out/eval -- Errors: definition.t0.err.d1.env.c: field not allowed: ./definition.cue:2:12 ./definition.cue:3:11 ./definition.cue:4:6 definition.t1.err.a.c: field not allowed: ./definition.cue:8:5 ./definition.cue:9:5 ./definition.cue:11:6 mutual.t4.ok.p0.z: cannot add to field b mutual.t4.ok.p0.z: cannot add to field c mutual.t4.ok.p4.z: cannot add to field b mutual.t4.ok.p4.z: cannot add to field c Result: (_|_){ // [eval] mutualBuiltin: (struct){ t1: (struct){ ok: (struct){ s3: (string){ strings.ContainsAny("dd") } s4: (_|_){ // [incomplete] mutualBuiltin.t1.ok.s4: invalid value "dd" (does not satisfy strings.ContainsAny(strings.ContainsAny("dd"))): error in call to strings.ContainsAny: non-concrete value string: // ./builtins.cue:6:6 // ./builtins.cue:5:6 // ./builtins.cue:7:6 } } } t2: (struct){ ok: (struct){ s3: (bool){ true } s5: (string){ "dd" } s6: (string){ "dd" } } } } comprehensions: (struct){ t1: (struct){ ok: (struct){ src: (#list){ 0: (string){ "foo" } } foo: (string){ "foo" } } } } definition: (_|_){ // [eval] t0: (_|_){ // [eval] err: (_|_){ // [eval] #D1: (#struct){ env: (#struct){ } } d1: (_|_){ // [eval] env: (_|_){ // [eval] c: (_|_){ // [eval] definition.t0.err.d1.env.c: field not allowed: // ./definition.cue:2:12 // ./definition.cue:3:11 // ./definition.cue:4:6 } } } } } t1: (_|_){ // [eval] err: (_|_){ // [eval] a: (_|_){ // [eval] c: (_|_){ // [eval] definition.t1.err.a.c: field not allowed: // ./definition.cue:8:5 // ./definition.cue:9:5 // ./definition.cue:11:6 } } #A: (#struct){ } } } t2: (struct){ ok: (struct){ p1: (struct){ #A: (#struct){ a: (int){ int } } x: (#struct){ a: (int){ int } c: (int){ int } } } p2: (struct){ #A: (#struct){ a: (int){ int } } x: (#struct){ a: (int){ int } c: (int){ int } } } p3: (struct){ x: (#struct){ a: (int){ int } c: (int){ int } } #A: (#struct){ a: (int){ int } } } p4: (struct){ x: (#struct){ a: (int){ int } c: (int){ int } } #A: (#struct){ a: (int){ int } } } } } } dynamic: (struct){ t1: (struct){ ok: (struct){ x: (struct){ y: (string){ "foo" } name: (string){ "x" } } foo: (struct){ name: (string){ "foo" } } } } t2: (struct){ ok: (struct){ foo: (#struct){ a: (#struct){ b: (#struct){ C: (int){ 1 } D: (int){ 2 } } } } #X: (#struct){ a: (#struct){ b: (#struct){ C: (int){ 1 } D: (int){ 2 } } } } } } } issue3194: (struct){ reduced: (#struct){ A: (number){ |(*(int){ 0 }, (number){ >10 }) } b: (number){ |(*(int){ 0 }, (number){ >10 }) } } } expr: (struct){ t1: (struct){ ok: (struct){ a: (float){ 5.0 } X: (float){ 5.0 } Y: (float){ 10.0 } } } t2: (struct){ ok: (struct){ A: (int){ 7 } X: (int){ 5 } } } t3: (struct){ ok: (struct){ p1: (struct){ a0: (float){ 5.0 } X: (float){ 5.0 } } p2: (struct){ b: (float){ 5.0 } Y: (float){ 5.0 } } } } t4: (struct){ ok: (struct){ a0: (float){ 5.0 } b0: (float){ 7.0 } a1: (float){ 7.0 } b1: (float){ 5.0 } X: (float){ 5.0 } } } } mutual: (_|_){ // [eval] t0: (struct){ ok: (struct){ c: (struct){ b: (int){ 2 } a: (int){ 1 } } e: (struct){ a: (int){ 1 } b: (int){ 2 } } } } t1: (struct){ ok: (struct){ a: (struct){ b: (struct){ b: (struct){ f: (int){ 1 } } f: (int){ 1 } } f: (int){ 1 } } } } t2: (struct){ ok: (struct){ x: (struct){ a: (struct){ a: (struct){ f: (int){ 1 } } e: (int){ 1 } } f: (int){ 1 } } y: (struct){ a: (struct){ a: (struct){ e: (int){ 1 } } f: (int){ 1 } } e: (int){ 1 } } } } t3: (struct){ ok: (struct){ d: (struct){ e: (struct){ f: (int){ 1 } g: (int){ 1 } } d: (struct){ e: (struct){ g: (int){ 1 } } } } e: (struct){ f: (int){ 1 } g: (int){ 1 } } } } t4: (_|_){ // [eval] ok: (_|_){ // [eval] p0: (_|_){ // [eval] z: (_|_){ // [eval] mutual.t4.ok.p0.z: cannot add to field b // mutual.t4.ok.p0.z: cannot add to field c d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } x: (struct){ b: (struct){ a: (int){ 1 } d: (struct){ b: (int){ 2 } } } } y: (struct){ c: (struct){ a: (int){ 1 } } } } p1: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } y: (struct){ c: (struct){ a: (int){ 1 } b: (int){ 2 } } } } p2: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } y: (struct){ c: (struct){ a: (int){ 1 } b: (int){ 2 } } } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } p3: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } b: (int){ 2 } a: (int){ 1 } } } y: (struct){ c: (struct){ b: (int){ 2 } a: (int){ 1 } } } z: (struct){ d: (struct){ b: (int){ 2 } a: (int){ 1 } } b: (int){ 2 } a: (int){ 1 } } } p4: (_|_){ // [eval] z: (_|_){ // [eval] mutual.t4.ok.p4.z: cannot add to field b // mutual.t4.ok.p4.z: cannot add to field c d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } a: (int){ 1 } } } y: (struct){ c: (struct){ a: (int){ 1 } } } } p5: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } b: (int){ 2 } a: (int){ 1 } } } y: (struct){ c: (struct){ b: (int){ 2 } a: (int){ 1 } } } z: (struct){ d: (struct){ b: (int){ 2 } a: (int){ 1 } } b: (int){ 2 } a: (int){ 1 } } } check: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } y: (struct){ c: (struct){ a: (int){ 1 } b: (int){ 2 } } } } } } } } -- out/evalalpha/stats -- Leaks: 278 Freed: 16 Reused: 16 Allocs: 278 Retain: 0 Unifications: 248 Conjuncts: 1900 Disjuncts: 44 -- out/evalalpha -- Errors: definition.t0.err.d1.env.c: field not allowed: ./definition.cue:3:11 definition.t1.err.a.c: field not allowed: ./definition.cue:9:5 Result: (_|_){ // [eval] mutualBuiltin: (struct){ t1: (struct){ ok: (struct){ s3: (string){ strings.ContainsAny("dd") } s4: (string){ "dd" } } } t2: (struct){ ok: (struct){ s3: (bool){ true } s5: (string){ "dd" } s6: (string){ "dd" } } } } comprehensions: (struct){ t1: (struct){ ok: (struct){ src: (#list){ 0: (string){ "foo" } } foo: (string){ "foo" } } } } definition: (_|_){ // [eval] t0: (_|_){ // [eval] err: (_|_){ // [eval] #D1: (#struct){ env: (#struct){ } } d1: (_|_){ // [eval] env: (_|_){ // [eval] c: (_|_){ // [eval] definition.t0.err.d1.env.c: field not allowed: // ./definition.cue:3:11 } } } } } t1: (_|_){ // [eval] err: (_|_){ // [eval] a: (_|_){ // [eval] c: (_|_){ // [eval] definition.t1.err.a.c: field not allowed: // ./definition.cue:9:5 } } #A: (#struct){ } } } t2: (struct){ ok: (struct){ p1: (struct){ #A: (#struct){ a: (int){ int } } x: (#struct){ c: (int){ int } a: (int){ int } } } p2: (struct){ #A: (#struct){ a: (int){ int } } x: (#struct){ c: (int){ int } a: (int){ int } } } p3: (struct){ x: (#struct){ c: (int){ int } a: (int){ int } } #A: (#struct){ a: (int){ int } } } p4: (struct){ x: (#struct){ c: (int){ int } a: (int){ int } } #A: (#struct){ a: (int){ int } } } } } } dynamic: (struct){ t1: (struct){ ok: (struct){ x: (struct){ y: (string){ "foo" } name: (string){ "x" } } foo: (struct){ name: (string){ "foo" } } } } t2: (struct){ ok: (struct){ foo: ~(dynamic.t2.ok.#X) #X: (#struct){ a: (#struct){ b: (#struct){ C: (int){ 1 } D: (int){ 2 } } } } } } } issue3194: (struct){ reduced: (#struct){ A: (number){ |(*(int){ 0 }, (number){ >10 }) } b: (number){ |(*(int){ 0 }, (number){ >10 }) } } } expr: (struct){ t1: (struct){ ok: (struct){ a: (float){ 5.0 } X: (float){ 5.0 } Y: (float){ 10.0 } } } t2: (struct){ ok: (struct){ A: (int){ 7 } X: (int){ 5 } } } t3: (struct){ ok: (struct){ p1: (struct){ a0: (float){ 5.0 } X: (float){ 5.0 } } p2: (struct){ b: (float){ 5.0 } Y: (float){ 5.0 } } } } t4: (struct){ ok: (struct){ a0: (float){ 5.0 } b0: (float){ 7.0 } a1: (float){ 7.0 } b1: (float){ 5.0 } X: (float){ 5.0 } } } } mutual: (struct){ t0: (struct){ ok: (struct){ c: (struct){ b: (int){ 2 } a: (int){ 1 } } e: (struct){ a: (int){ 1 } b: (int){ 2 } } } } t1: (struct){ ok: (struct){ a: (struct){ b: (struct){ b: (struct){ f: (int){ 1 } } f: (int){ 1 } } f: (int){ 1 } } } } t2: (struct){ ok: (struct){ x: (struct){ a: (struct){ a: (struct){ f: (int){ 1 } } e: (int){ 1 } } f: (int){ 1 } } y: (struct){ a: (struct){ a: (struct){ e: (int){ 1 } } f: (int){ 1 } } e: (int){ 1 } } } } t3: (struct){ ok: (struct){ d: (struct){ e: (struct){ f: (int){ 1 } g: (int){ 1 } } d: (struct){ e: (struct){ g: (int){ 1 } } } } e: (struct){ f: (int){ 1 } g: (int){ 1 } } } } t4: (struct){ ok: (struct){ p0: (struct){ z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } y: (struct){ c: ~(mutual.t4.ok.p0.z.d) } } p1: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } } } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } y: (struct){ c: ~(mutual.t4.ok.p1.z.d) } } p2: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } } } y: (struct){ c: ~(mutual.t4.ok.p2.z.d) } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } p3: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } } } y: (struct){ c: ~(mutual.t4.ok.p3.z.d) } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } p4: (struct){ z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } y: (struct){ c: ~(mutual.t4.ok.p4.z.d) } } p5: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } } } y: (struct){ c: ~(mutual.t4.ok.p5.z.d) } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } } check: (struct){ x: (struct){ b: (struct){ d: (struct){ b: (int){ 2 } } } } z: (struct){ d: (struct){ a: (int){ 1 } b: (int){ 2 } } a: (int){ 1 } b: (int){ 2 } } y: (struct){ c: ~(mutual.t4.ok.check.z.d) } } } } } } -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 4 -Freed: 285 -Reused: 273 -Allocs: 16 -Retain: 170 +Leaks: 278 +Freed: 16 +Reused: 16 +Allocs: 278 +Retain: 0 -Unifications: 269 -Conjuncts: 1619 -Disjuncts: 436 +Unifications: 248 +Conjuncts: 1900 +Disjuncts: 44 -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,16 +1,8 @@ Errors: definition.t0.err.d1.env.c: field not allowed: - ./definition.cue:2:12 ./definition.cue:3:11 - ./definition.cue:4:6 definition.t1.err.a.c: field not allowed: - ./definition.cue:8:5 ./definition.cue:9:5 - ./definition.cue:11:6 -mutual.t4.ok.p0.z: cannot add to field b -mutual.t4.ok.p0.z: cannot add to field c -mutual.t4.ok.p4.z: cannot add to field b -mutual.t4.ok.p4.z: cannot add to field c Result: (_|_){ @@ -19,12 +11,7 @@ t1: (struct){ ok: (struct){ s3: (string){ strings.ContainsAny("dd") } - s4: (_|_){ - // [incomplete] mutualBuiltin.t1.ok.s4: invalid value "dd" (does not satisfy strings.ContainsAny(strings.ContainsAny("dd"))): error in call to strings.ContainsAny: non-concrete value string: - // ./builtins.cue:6:6 - // ./builtins.cue:5:6 - // ./builtins.cue:7:6 - } + s4: (string){ "dd" } } } t2: (struct){ @@ -61,9 +48,7 @@ // [eval] c: (_|_){ // [eval] definition.t0.err.d1.env.c: field not allowed: - // ./definition.cue:2:12 // ./definition.cue:3:11 - // ./definition.cue:4:6 } } } @@ -77,9 +62,7 @@ // [eval] c: (_|_){ // [eval] definition.t1.err.a.c: field not allowed: - // ./definition.cue:8:5 // ./definition.cue:9:5 - // ./definition.cue:11:6 } } #A: (#struct){ @@ -93,32 +76,32 @@ a: (int){ int } } x: (#struct){ - a: (int){ int } - c: (int){ int } - } - } - p2: (struct){ - #A: (#struct){ - a: (int){ int } - } - x: (#struct){ - a: (int){ int } - c: (int){ int } - } - } - p3: (struct){ - x: (#struct){ - a: (int){ int } - c: (int){ int } - } - #A: (#struct){ - a: (int){ int } - } - } - p4: (struct){ - x: (#struct){ - a: (int){ int } - c: (int){ int } + c: (int){ int } + a: (int){ int } + } + } + p2: (struct){ + #A: (#struct){ + a: (int){ int } + } + x: (#struct){ + c: (int){ int } + a: (int){ int } + } + } + p3: (struct){ + x: (#struct){ + c: (int){ int } + a: (int){ int } + } + #A: (#struct){ + a: (int){ int } + } + } + p4: (struct){ + x: (#struct){ + c: (int){ int } + a: (int){ int } } #A: (#struct){ a: (int){ int } @@ -141,14 +124,7 @@ } t2: (struct){ ok: (struct){ - foo: (#struct){ - a: (#struct){ - b: (#struct){ - C: (int){ 1 } - D: (int){ 2 } - } - } - } + foo: ~(dynamic.t2.ok.#X) #X: (#struct){ a: (#struct){ b: (#struct){ @@ -202,8 +178,7 @@ } } } - mutual: (_|_){ - // [eval] + mutual: (struct){ t0: (struct){ ok: (struct){ c: (struct){ @@ -270,135 +245,110 @@ } } } - t4: (_|_){ - // [eval] - ok: (_|_){ - // [eval] - p0: (_|_){ - // [eval] - z: (_|_){ - // [eval] mutual.t4.ok.p0.z: cannot add to field b - // mutual.t4.ok.p0.z: cannot add to field c - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - x: (struct){ - b: (struct){ - a: (int){ 1 } - d: (struct){ - b: (int){ 2 } - } - } - } - y: (struct){ - c: (struct){ - a: (int){ 1 } - } - } - } - p1: (struct){ - x: (struct){ - b: (struct){ - d: (struct){ - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - } - z: (struct){ - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - y: (struct){ - c: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - } - } - p2: (struct){ - x: (struct){ - b: (struct){ - d: (struct){ - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - } - y: (struct){ - c: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - } - z: (struct){ - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - } - p3: (struct){ - x: (struct){ - b: (struct){ - d: (struct){ - b: (int){ 2 } - } - b: (int){ 2 } - a: (int){ 1 } - } - } - y: (struct){ - c: (struct){ - b: (int){ 2 } - a: (int){ 1 } - } - } - z: (struct){ - d: (struct){ - b: (int){ 2 } - a: (int){ 1 } - } - b: (int){ 2 } - a: (int){ 1 } - } - } - p4: (_|_){ - // [eval] - z: (_|_){ - // [eval] mutual.t4.ok.p4.z: cannot add to field b - // mutual.t4.ok.p4.z: cannot add to field c - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - x: (struct){ - b: (struct){ - d: (struct){ - b: (int){ 2 } - } - a: (int){ 1 } - } - } - y: (struct){ - c: (struct){ - a: (int){ 1 } - } + t4: (struct){ + ok: (struct){ + p0: (struct){ + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + x: (struct){ + b: (struct){ + d: (struct){ + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + } + y: (struct){ + c: ~(mutual.t4.ok.p0.z.d) + } + } + p1: (struct){ + x: (struct){ + b: (struct){ + d: (struct){ + b: (int){ 2 } + } + } + } + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + y: (struct){ + c: ~(mutual.t4.ok.p1.z.d) + } + } + p2: (struct){ + x: (struct){ + b: (struct){ + d: (struct){ + b: (int){ 2 } + } + } + } + y: (struct){ + c: ~(mutual.t4.ok.p2.z.d) + } + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + } + p3: (struct){ + x: (struct){ + b: (struct){ + d: (struct){ + b: (int){ 2 } + } + } + } + y: (struct){ + c: ~(mutual.t4.ok.p3.z.d) + } + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + } + p4: (struct){ + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + x: (struct){ + b: (struct){ + d: (struct){ + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + } + y: (struct){ + c: ~(mutual.t4.ok.p4.z.d) } } p5: (struct){ @@ -407,23 +357,18 @@ d: (struct){ b: (int){ 2 } } - b: (int){ 2 } - a: (int){ 1 } - } - } - y: (struct){ - c: (struct){ - b: (int){ 2 } - a: (int){ 1 } - } - } - z: (struct){ - d: (struct){ - b: (int){ 2 } - a: (int){ 1 } - } - b: (int){ 2 } - a: (int){ 1 } + } + } + y: (struct){ + c: ~(mutual.t4.ok.p5.z.d) + } + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } } } check: (struct){ @@ -432,23 +377,18 @@ d: (struct){ b: (int){ 2 } } - a: (int){ 1 } - b: (int){ 2 } - } - } - z: (struct){ - d: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } - a: (int){ 1 } - b: (int){ 2 } - } - y: (struct){ - c: (struct){ - a: (int){ 1 } - b: (int){ 2 } - } + } + } + z: (struct){ + d: (struct){ + a: (int){ 1 } + b: (int){ 2 } + } + a: (int){ 1 } + b: (int){ 2 } + } + y: (struct){ + c: ~(mutual.t4.ok.check.z.d) } } } -- diff/explanation -- Bug fixes -- diff/todo/p2 -- Reordering / positions. -- out/compile -- --- builtins.cue { mutualBuiltin: { t1: { ok: { s3: 〈import;strings〉.ContainsAny(〈0;s4〉) s4: 〈import;strings〉.ContainsAny(〈0;s3〉) s4: "dd" } } } mutualBuiltin: { t2: { ok: { s3: 〈import;strings〉.ContainsAny(〈0;s5〉, "dd") s5: 〈0;s6〉 s6: "dd" } } } } --- comprehensions.cue { comprehensions: { t1: { ok: { src: [ "foo", ] for _, v in 〈0;src〉 { "\(〈1;v〉)": 〈1;v〉 } } } } } --- definition.cue { definition: { t0: { err: { #D1: { env: {} } d1: { env: { c: "C" } } d1: 〈0;#D1〉 } } } definition: { t1: { err: { a: 〈0;#A〉 a: { c: 1 } #A: {} } } } definition: { t2: { ok: { p1: { #A: { ... { a: int } } x: (〈0;#A〉 & { c: int }) } } } } definition: { t2: { ok: { p2: { #A: { { a: int } ... } x: (〈0;#A〉 & { c: int }) } } } } definition: { t2: { ok: { p3: { x: (〈0;#A〉 & { c: int }) #A: { ... { a: int } } } } } } definition: { t2: { ok: { p4: { x: (〈0;#A〉 & { c: int }) #A: { { a: int } ... } } } } } } --- dynamic.cue { dynamic: { t1: { ok: { [string]: { name: 〈1;-〉 } 〈0;x〉.y: {} x: { y: "foo" } } } } dynamic: { t2: { ok: { foo: 〈0;#X〉 #X: { a: { b: { C: 1 } } for _, _ in 〈0;a〉 { a: { "b": { D: 2 } } } } } } } } --- equality.cue { issue3194: { reduced: { A: (*0|>10) A: (*0|>10) { out: close({ b: 〈2;A〉 }) out: { b: 〈2;A〉 } }.out } } } --- expr.cue { expr: { t1: { ok: { a: 〈0;X〉 X: 5.0 X: (〈0;Y〉 / 2) Y: (〈0;a〉 * 2) } } } expr: { t2: { ok: { A: (〈0;X〉 + 2) X: 5 X: (〈0;A〉 - 2) } } } expr: { t3: { ok: { p1: { a0: 〈0;X〉 X: 5.0 X: (〈0;a0〉 * 1) } } } } expr: { t3: { ok: { p2: { b: (〈0;Y〉 * 1) Y: (〈0;b〉 * 1) Y: 5.0 } } } } expr: { t4: { ok: { a0: 〈0;X〉 b0: 〈0;a1〉 a1: (〈0;a0〉 + 2) b1: (〈0;b0〉 - 2) a0: 〈0;X〉 X: 〈0;b1〉 X: 5.0 } } } } --- in.cue { mutual: { t0: { ok: { c: (〈0;e〉 & { b: 2 }) e: { a: 1 } e: 〈0;c〉 } } } mutual: { t1: { ok: { a: { 〈0;b〉 b: { b: { f: 1 } } } a: 〈0;a〉.b a: { b: { b: { f: 1 } } } } } } mutual: { t2: { ok: { x: { a: { a: { f: 1 } } } x: 〈0;y〉.a y: { a: { a: { e: 1 } } } y: 〈0;x〉.a } } } mutual: { t3: { ok: { d: { e: { f: 1 } } 〈0;d〉 d: { d: { e: { g: 1 } } } } } } mutual: { t4: { ok: { p0: { z: 〈0;x〉.b x: { b: 〈1;y〉.c } x: { b: { d: { b: 2 } } } y: { c: 〈1;z〉.d } z: { d: { a: 1 } } } p1: { x: { b: 〈1;y〉.c } z: 〈0;x〉.b x: { b: { d: { b: 2 } } } y: { c: 〈1;z〉.d } z: { d: { a: 1 } } } p2: { x: { b: 〈1;y〉.c } x: { b: { d: { b: 2 } } } y: { c: 〈1;z〉.d } z: 〈0;x〉.b z: { d: { a: 1 } } } p3: { x: { b: { d: { b: 2 } } } y: { c: 〈1;z〉.d } z: 〈0;x〉.b x: { b: 〈1;y〉.c } z: { d: { a: 1 } } } p4: { z: 〈0;x〉.b x: { b: { d: { b: 2 } } } y: { c: 〈1;z〉.d } x: { b: 〈1;y〉.c } z: { d: { a: 1 } } } p5: { x: { b: { d: { b: 2 } } } y: { c: 〈1;z〉.d } x: { b: 〈1;y〉.c } z: 〈0;x〉.b z: { d: { a: 1 } } } check: ((((〈0;p1〉 & 〈0;p2〉) & 〈0;p3〉) & 〈0;p4〉) & 〈0;p5〉) } } } } cue-lang-cue-db9cc73/cue/testdata/eval/v0.7errorprop.txtar000066400000000000000000000024241474664451600235470ustar00rootroot00000000000000// NOTE: do not add more tests to this file, as it may obfuscate the test case. -- in.cue -- a: #A a: c: 1 #A: {} -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 1 Allocs: 3 Retain: 1 Unifications: 4 Conjuncts: 6 Disjuncts: 5 -- out/evalalpha -- Errors: a.c: field not allowed: ./in.cue:2:4 Result: (_|_){ // [eval] a: (_|_){ // [eval] c: (_|_){ // [eval] a.c: field not allowed: // ./in.cue:2:4 } } #A: (#struct){ } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,8 +1,6 @@ Errors: a.c: field not allowed: - ./in.cue:1:4 ./in.cue:2:4 - ./in.cue:3:5 Result: (_|_){ @@ -11,9 +9,7 @@ // [eval] c: (_|_){ // [eval] a.c: field not allowed: - // ./in.cue:1:4 // ./in.cue:2:4 - // ./in.cue:3:5 } } #A: (#struct){ -- diff/todo/p2 -- Missing error positions. -- out/eval -- Errors: a.c: field not allowed: ./in.cue:1:4 ./in.cue:2:4 ./in.cue:3:5 Result: (_|_){ // [eval] a: (_|_){ // [eval] c: (_|_){ // [eval] a.c: field not allowed: // ./in.cue:1:4 // ./in.cue:2:4 // ./in.cue:3:5 } } #A: (#struct){ } } -- out/compile -- --- in.cue { a: 〈0;#A〉 a: { c: 1 } #A: {} } cue-lang-cue-db9cc73/cue/testdata/export/000077500000000000000000000000001474664451600204065ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/export/000.txtar000066400000000000000000000005251474664451600217730ustar00rootroot00000000000000-- in.cue -- "hello" -- out/def -- "hello" -- out/export -- "hello" -- out/yaml -- hello -- out/json -- "hello" -- out/legacy-debug -- "hello" -- out/compile -- --- in.cue { "hello" } -- out/eval/stats -- Leaks: 0 Freed: 1 Reused: 0 Allocs: 1 Retain: 0 Unifications: 1 Conjuncts: 2 Disjuncts: 1 -- out/eval -- (string){ "hello" } cue-lang-cue-db9cc73/cue/testdata/export/001.txtar000066400000000000000000000005271474664451600217760ustar00rootroot00000000000000-- in.cue -- 'hello' -- out/def -- 'hello' -- out/export -- 'hello' -- out/yaml -- hello -- out/json -- "aGVsbG8=" -- out/legacy-debug -- 'hello' -- out/compile -- --- in.cue { 'hello' } -- out/eval/stats -- Leaks: 0 Freed: 1 Reused: 0 Allocs: 1 Retain: 0 Unifications: 1 Conjuncts: 2 Disjuncts: 1 -- out/eval -- (bytes){ 'hello' } cue-lang-cue-db9cc73/cue/testdata/export/002.txtar000066400000000000000000000007551474664451600220020ustar00rootroot00000000000000-- in.cue -- 'hello\nworld' -- out/def -- ''' hello world ''' -- out/export -- ''' hello world ''' -- out/yaml -- |- hello world -- out/json -- "aGVsbG8Kd29ybGQ=" -- out/legacy-debug -- ''' hello world ''' -- out/compile -- --- in.cue { 'hello\nworld' } -- out/eval/stats -- Leaks: 0 Freed: 1 Reused: 0 Allocs: 1 Retain: 0 Unifications: 1 Conjuncts: 2 Disjuncts: 1 -- out/eval -- (bytes){ 'hello\nworld' } cue-lang-cue-db9cc73/cue/testdata/export/003.txtar000066400000000000000000000007521474664451600220000ustar00rootroot00000000000000-- in.cue -- "hello\nworld" -- out/def -- """ hello world """ -- out/export -- """ hello world """ -- out/yaml -- |- hello world -- out/json -- "hello\nworld" -- out/legacy-debug -- """ hello world """ -- out/compile -- --- in.cue { "hello\nworld" } -- out/eval/stats -- Leaks: 0 Freed: 1 Reused: 0 Allocs: 1 Retain: 0 Unifications: 1 Conjuncts: 2 Disjuncts: 1 -- out/eval -- (string){ "hello\nworld" } cue-lang-cue-db9cc73/cue/testdata/export/004.txtar000066400000000000000000000007071474664451600220010ustar00rootroot00000000000000-- in.cue -- { $type: 3 "_": int "_foo": int _bar: int } -- out/def -- $type: 3 "_": int "_foo": int _bar: int -- out/compile -- --- in.cue { { $type: 3 "_": int "_foo": int _bar: int } } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 3 Allocs: 2 Retain: 0 Unifications: 5 Conjuncts: 6 Disjuncts: 5 -- out/eval -- (struct){ $type: (int){ 3 } "_": (int){ int } "_foo": (int){ int } _bar: (int){ int } } cue-lang-cue-db9cc73/cue/testdata/export/005.txtar000066400000000000000000000007611474664451600220020ustar00rootroot00000000000000-- in.cue -- {a: 1, b: a + 2, c: null, d: true, e: _, f: string} -- out/def -- a: 1 b: 3 c: null d: true e: _ f: string -- out/compile -- --- in.cue { { a: 1 b: (〈0;a〉 + 2) c: null d: true e: _ f: string } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 5 Allocs: 2 Retain: 0 Unifications: 7 Conjuncts: 8 Disjuncts: 7 -- out/eval -- (struct){ a: (int){ 1 } b: (int){ 3 } c: (null){ null } d: (bool){ true } e: (_){ _ } f: (string){ string } } cue-lang-cue-db9cc73/cue/testdata/export/006.txtar000066400000000000000000000014461474664451600220040ustar00rootroot00000000000000-- in.cue -- {a: {b: 2.0, s: "abc"}, b: a.b, c: a.c, d: a["d"], e: a.t[2:3]} -- out/def -- a: { b: 2.0 s: "abc" } b: 2.0 c: a.c d: a["d"] e: a.t[2:3] -- out/compile -- --- in.cue { { a: { b: 2.0 s: "abc" } b: 〈0;a〉.b c: 〈0;a〉.c d: 〈0;a〉["d"] e: 〈0;a〉.t[2:3] } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 5 Allocs: 3 Retain: 0 Unifications: 8 Conjuncts: 14 Disjuncts: 8 -- out/eval -- (struct){ a: (struct){ b: (float){ 2.0 } s: (string){ "abc" } } b: (float){ 2.0 } c: (_|_){ // [incomplete] c: undefined field: c: // ./in.cue:1:38 } d: (_|_){ // [incomplete] d: undefined field: d: // ./in.cue:1:46 } e: (_|_){ // [incomplete] e: undefined field: t: // ./in.cue:1:57 } } cue-lang-cue-db9cc73/cue/testdata/export/007.txtar000066400000000000000000000017601474664451600220040ustar00rootroot00000000000000-- in.cue -- { #a: {b: 2.0, s: "abc"} b: #a.b c: #a.c d: #a["d"] e: #a.t[2:3] } -- out/def -- #a: { b: 2.0 s: "abc" } b: 2.0 c: _|_ // undefined field "c" d: _|_ // undefined field "d" e: _|_ // undefined field "t" -- out/compile -- --- in.cue { { #a: { b: 2.0 s: "abc" } b: 〈0;#a〉.b c: 〈0;#a〉.c d: 〈0;#a〉["d"] e: 〈0;#a〉.t[2:3] } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 5 Allocs: 3 Retain: 0 Unifications: 8 Conjuncts: 10 Disjuncts: 8 -- out/eval -- Errors: c: undefined field: c: ./in.cue:4:8 d: undefined field: d: ./in.cue:5:8 e: undefined field: t: ./in.cue:6:8 Result: (_|_){ // [eval] #a: (#struct){ b: (float){ 2.0 } s: (string){ "abc" } } b: (float){ 2.0 } c: (_|_){ // [eval] c: undefined field: c: // ./in.cue:4:8 } d: (_|_){ // [eval] d: undefined field: d: // ./in.cue:5:8 } e: (_|_){ // [eval] e: undefined field: t: // ./in.cue:6:8 } } cue-lang-cue-db9cc73/cue/testdata/export/008.txtar000066400000000000000000000024021474664451600217770ustar00rootroot00000000000000-- in.cue -- {a: [ 3 & 4]} -- out/def -- a: [_|_, // conflicting values 3 and 4 ] -- out/compile -- --- in.cue { { a: [ (3 & 4), ] } } -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 0 Allocs: 3 Retain: 0 Unifications: 3 Conjuncts: 5 Disjuncts: 3 -- out/evalalpha -- Errors: a.0: conflicting values 4 and 3: ./in.cue:1:7 ./in.cue:1:11 Result: (_|_){ // [eval] a: (_|_){ // [eval] 0: (_|_){ // [eval] a.0: conflicting values 4 and 3: // ./in.cue:1:7 // ./in.cue:1:11 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,6 +1,5 @@ Errors: a.0: conflicting values 4 and 3: - ./in.cue:1:1 ./in.cue:1:7 ./in.cue:1:11 @@ -11,7 +10,6 @@ // [eval] 0: (_|_){ // [eval] a.0: conflicting values 4 and 3: - // ./in.cue:1:1 // ./in.cue:1:7 // ./in.cue:1:11 } -- diff/todo/p2 -- Missing error positions. -- out/eval -- Errors: a.0: conflicting values 4 and 3: ./in.cue:1:1 ./in.cue:1:7 ./in.cue:1:11 Result: (_|_){ // [eval] a: (_|_){ // [eval] 0: (_|_){ // [eval] a.0: conflicting values 4 and 3: // ./in.cue:1:1 // ./in.cue:1:7 // ./in.cue:1:11 } } } cue-lang-cue-db9cc73/cue/testdata/export/009.txtar000066400000000000000000000016151474664451600220050ustar00rootroot00000000000000-- in.cue -- import "list" { a: list.Repeat([int], 5) a: [1, 2, ...] e: [...int] e: [1, 2, ...] f: [1, 2, ...] } -- out/def -- a: [1, 2, int, int, int] b: <=5*[int] & [1, 2, ...] c: (>=3 & <=5)*[int] & [1, 2, ...] d: >=2*[int] & [1, 2, ...] e: [1, 2, ...int] f: [1, 2, ...] -- out/compile -- --- in.cue { { a: 〈import;list〉.Repeat([ int, ], 5) a: [ 1, 2, ..., ] e: [ ...int, ] e: [ 1, 2, ..., ] f: [ 1, 2, ..., ] } } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 11 Allocs: 4 Retain: 1 Unifications: 15 Conjuncts: 31 Disjuncts: 16 -- out/eval -- (struct){ a: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ int } 3: (int){ int } 4: (int){ int } } e: (list){ 0: (int){ 1 } 1: (int){ 2 } } f: (list){ 0: (int){ 1 } 1: (int){ 2 } } } cue-lang-cue-db9cc73/cue/testdata/export/010.txtar000066400000000000000000000016271474664451600220000ustar00rootroot00000000000000raw: true -- in.cue -- import "list" { a: list.Repeat([int], 5) a: [1, 2, ...] e: [...int] e: [1, 2, ...] f: [1, 2, ...] } -- out/def -- a: [1, 2, int, int, int] b: <=5*[int] & [1, 2, ...] c: (>=3 & <=5)*[int] & [1, 2, ...] d: >=2*[int] & [1, 2, ...] e: [1, 2, ...int] f: [1, 2, ...] -- out/compile -- --- in.cue { { a: 〈import;list〉.Repeat([ int, ], 5) a: [ 1, 2, ..., ] e: [ ...int, ] e: [ 1, 2, ..., ] f: [ 1, 2, ..., ] } } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 11 Allocs: 4 Retain: 1 Unifications: 15 Conjuncts: 31 Disjuncts: 16 -- out/eval -- (struct){ a: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ int } 3: (int){ int } 4: (int){ int } } e: (list){ 0: (int){ 1 } 1: (int){ 2 } } f: (list){ 0: (int){ 1 } 1: (int){ 2 } } } cue-lang-cue-db9cc73/cue/testdata/export/011.txtar000066400000000000000000000010511474664451600217700ustar00rootroot00000000000000raw: true -- in.cue -- {a: {b: []}, c: a.b, d: a["b"]} -- out/def -- a: { b: [] } c: [] d: [] -- out/export -- a: { b: [] } c: [] d: [] -- out/yaml -- a: b: [] c: [] d: [] -- out/json -- {"a":{"b":[]},"c":[],"d":[]} -- out/compile -- --- in.cue { { a: { b: [] } c: 〈0;a〉.b d: 〈0;a〉["b"] } } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 2 Allocs: 3 Retain: 0 Unifications: 5 Conjuncts: 8 Disjuncts: 5 -- out/eval -- (struct){ a: (struct){ b: (#list){ } } c: (#list){ } d: (#list){ } } cue-lang-cue-db9cc73/cue/testdata/export/012.txtar000066400000000000000000000011051474664451600217710ustar00rootroot00000000000000raw: true -- in.cue -- {a: *"foo" | *"bar" | *string | int, b: a[2:3]} -- out/def -- a: *string | int b: _|_ // cannot slice a (type string) -- out/compile -- --- in.cue { { a: (*"foo"|*"bar"|*string|int) b: 〈0;a〉[2:3] } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 1 Allocs: 6 Retain: 0 Unifications: 3 Conjuncts: 12 Disjuncts: 7 -- out/eval -- (struct){ a: ((int|string)){ |(*(string){ "foo" }, *(string){ "bar" }, *(string){ string }, (int){ int }) } b: (_|_){ // [incomplete] b: non-concrete slice subject a: // ./in.cue:1:41 } } cue-lang-cue-db9cc73/cue/testdata/export/013.txtar000066400000000000000000000005031474664451600217730ustar00rootroot00000000000000-- in.cue -- { a: >=0 & <=10 & !=1 } -- out/def -- a: >=0 & <=10 & !=1 -- out/compile -- --- in.cue { { a: ((>=0 & <=10) & !=1) } } -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 0 Unifications: 2 Conjuncts: 5 Disjuncts: 2 -- out/eval -- (struct){ a: (number){ &(>=0, <=10, !=1) } } cue-lang-cue-db9cc73/cue/testdata/export/014.txtar000066400000000000000000000005151474664451600217770ustar00rootroot00000000000000raw: true -- in.cue -- { a: >=0 & <=10 & !=1 } -- out/def -- a: >=0 & <=10 & !=1 -- out/compile -- --- in.cue { { a: ((>=0 & <=10) & !=1) } } -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 0 Unifications: 2 Conjuncts: 5 Disjuncts: 2 -- out/eval -- (struct){ a: (number){ &(>=0, <=10, !=1) } } cue-lang-cue-db9cc73/cue/testdata/export/015.txtar000066400000000000000000000007541474664451600220050ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { a: (*1 | 2) & (1 | *2) b: [(*1 | 2) & (1 | *2)] } -- out/def -- a: 1 | 2 | *_|_ b: [1 | 2 | *_|_] -- out/compile -- --- in.cue { { a: ((*1|2) & (1|*2)) b: [ ((*1|2) & (1|*2)), ] } } -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 9 Allocs: 7 Retain: 0 Unifications: 4 Conjuncts: 19 Disjuncts: 16 -- out/eval -- (struct){ a: (int){ |((int){ 1 }, (int){ 2 }) } b: (#list){ 0: (int){ |((int){ 1 }, (int){ 2 }) } } } cue-lang-cue-db9cc73/cue/testdata/export/016.txtar000066400000000000000000000043161474664451600220040ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { u16: int & >=0 & <=65535 u32: uint32 u64: uint64 u128: uint128 u8: uint8 ua: uint16 & >0 us: >=0 & <10_000 & int i16: >=-32768 & int & <=32767 i32: int32 & >0 i64: int64 i128: int128 f64: float64 fi: float64 & int } -- out/def -- u16: uint16 u32: uint32 u64: uint64 u128: uint128 u8: uint8 ua: uint16 & >0 us: uint & <10000 i16: int16 i32: int32 & >0 i64: int64 i128: int128 f64: float64 fi: int & float64 -- out/compile -- --- in.cue { { u16: ((int & >=0) & <=65535) u32: &(int, >=0, <=4294967295) u64: &(int, >=0, <=18446744073709551615) u128: &(int, >=0, <=340282366920938463463374607431768211455) u8: &(int, >=0, <=255) ua: (&(int, >=0, <=65535) & >0) us: ((>=0 & <10000) & int) i16: ((>=-32768 & int) & <=32767) i32: (&(int, >=-2147483648, <=2147483647) & >0) i64: &(int, >=-9223372036854775808, <=9223372036854775807) i128: &(int, >=-170141183460469231731687303715884105728, <=170141183460469231731687303715884105727) f64: &(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) fi: (&(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) & int) } } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 12 Allocs: 2 Retain: 0 Unifications: 14 Conjuncts: 24 Disjuncts: 14 -- out/eval -- (struct){ u16: (int){ &(>=0, <=65535, int) } u32: (int){ &(>=0, <=4294967295, int) } u64: (int){ &(>=0, <=18446744073709551615, int) } u128: (int){ &(>=0, <=340282366920938463463374607431768211455, int) } u8: (int){ &(>=0, <=255, int) } ua: (int){ &(>0, <=65535, int) } us: (int){ &(>=0, <10000, int) } i16: (int){ &(>=-32768, <=32767, int) } i32: (int){ &(>0, <=2147483647, int) } i64: (int){ &(>=-9223372036854775808, <=9223372036854775807, int) } i128: (int){ &(>=-170141183460469231731687303715884105728, <=170141183460469231731687303715884105727, int) } f64: (number){ &(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308) } fi: (int){ &(>=-1.797693134862315708145274237317043567981E+308, <=1.797693134862315708145274237317043567981E+308, int) } } cue-lang-cue-db9cc73/cue/testdata/export/017.txtar000066400000000000000000000012161474664451600220010ustar00rootroot00000000000000raw: true -- in.cue -- {a: [1, 2], b: {for k, v in a if v > 1 {"\(k)": v}}} -- out/def -- a: [1, 2] b: { "1": 2 } -- out/export -- a: [1, 2] b: { "1": 2 } -- out/yaml -- a: - 1 - 2 b: "1": 2 -- out/json -- {"a":[1,2],"b":{"1":2}} -- out/compile -- --- in.cue { { a: [ 1, 2, ] b: { for k, v in 〈1;a〉 if (〈0;v〉 > 1) { "\(〈1;k〉)": 〈1;v〉 } } } } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 3 Allocs: 3 Retain: 0 Unifications: 6 Conjuncts: 9 Disjuncts: 6 -- out/eval -- (struct){ a: (#list){ 0: (int){ 1 } 1: (int){ 2 } } b: (struct){ "1": (int){ 2 } } } cue-lang-cue-db9cc73/cue/testdata/export/018.txtar000066400000000000000000000011361474664451600220030ustar00rootroot00000000000000raw: true -- in.cue -- {a: [1, 2], b: [for k, v in a {v}]} -- out/def -- a: [1, 2] b: [1, 2] -- out/export -- a: [1, 2] b: [1, 2] -- out/yaml -- a: - 1 - 2 b: - 1 - 2 -- out/json -- {"a":[1,2],"b":[1,2]} -- out/compile -- --- in.cue { { a: [ 1, 2, ] b: [ for k, v in 〈1;a〉 { 〈1;v〉 }, ] } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 4 Allocs: 3 Retain: 0 Unifications: 7 Conjuncts: 12 Disjuncts: 7 -- out/eval -- (struct){ a: (#list){ 0: (int){ 1 } 1: (int){ 2 } } b: (#list){ 0: (int){ 1 } 1: (int){ 2 } } } cue-lang-cue-db9cc73/cue/testdata/export/019.txtar000066400000000000000000000010071474664451600220010ustar00rootroot00000000000000raw: true -- in.cue -- {a: >=0 & <=10, b: "Count: \(a) times"} -- out/def -- a: >=0 & <=10 b: "Count: \(a) times" -- out/compile -- --- in.cue { { a: (>=0 & <=10) b: "Count: \(〈0;a〉) times" } } -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 1 Allocs: 2 Retain: 0 Unifications: 3 Conjuncts: 9 Disjuncts: 3 -- out/eval -- (struct){ a: (number){ &(>=0, <=10) } b: (_|_){ // [incomplete] b: invalid interpolation: non-concrete value >=0 & <=10 (type number): // ./in.cue:1:20 } } cue-lang-cue-db9cc73/cue/testdata/export/020.txtar000066400000000000000000000006271474664451600220000ustar00rootroot00000000000000raw: true -- in.cue -- {a: "", b: len(a)} -- out/def -- a: "" b: 0 -- out/export -- a: "" b: 0 -- out/yaml -- a: "" b: 0 -- out/json -- {"a":"","b":0} -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 1 Allocs: 2 Retain: 0 Unifications: 3 Conjuncts: 4 Disjuncts: 3 -- out/eval -- (struct){ a: (string){ "" } b: (int){ 0 } } -- out/compile -- --- in.cue { { a: "" b: len(〈0;a〉) } } cue-lang-cue-db9cc73/cue/testdata/export/021.txtar000066400000000000000000000014051474664451600217740ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { b: { idx: a[str] str: string } b: a: b: 4 a: b: 3 } -- out/def -- A = a b: { idx: A[str] a: { b: 4 } str: string } a: { b: 3 } -- out/compile -- --- in.cue { { b: { idx: 〈1;a〉[〈0;str〉] str: string } b: { a: { b: 4 } } a: { b: 3 } } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 3 Allocs: 5 Retain: 10 Unifications: 8 Conjuncts: 14 Disjuncts: 18 -- out/eval -- (struct){ b: (struct){ idx: (_|_){ // [incomplete] b.idx: invalid non-ground value string (must be concrete string): // ./in.cue:4:8 } str: (string){ string } a: (struct){ b: (int){ 4 } } } a: (struct){ b: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/export/022.txtar000066400000000000000000000032431474664451600217770ustar00rootroot00000000000000raw: true eval: true noOpt: true -- in.cue -- { job: [Name=_]: { name: Name replicas: uint | *1 @protobuf(10) command: string } job: list: command: "ls" job: nginx: { command: "nginx" replicas: 2 } } -- out/def -- job: { {[Name=string]: { name: Name, replicas: >=0 | *1 @protobuf(10), command: string }} list: { name: "list" replicas: >=0 | *1 @protobuf(10) command: "ls" } nginx: { name: "nginx" replicas: 2 @protobuf(10) command: "nginx" } } -- out/export -- job: { list: { name: "list" replicas: 1 @protobuf(10) command: "ls" } nginx: { name: "nginx" replicas: 2 @protobuf(10) command: "nginx" } } -- out/yaml -- job: list: name: list replicas: 1 command: ls nginx: name: nginx replicas: 2 command: nginx -- out/json -- {"job":{"list":{"name":"list","replicas":1,"command":"ls"},"nginx":{"name":"nginx","replicas":2,"command":"nginx"}}} -- out/compile -- --- in.cue { { job: { [_]: { name: 〈1;-〉 replicas: (&(int, >=0)|*1) command: string } } job: { list: { command: "ls" } } job: { nginx: { command: "nginx" replicas: 2 } } } } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 8 Allocs: 6 Retain: 0 Unifications: 10 Conjuncts: 22 Disjuncts: 14 -- out/eval -- (struct){ job: (struct){ list: (struct){ command: (string){ "ls" } name: (string){ "list" } replicas: (int){ |(*(int){ 1 }, (int){ &(>=0, int) }) } } nginx: (struct){ command: (string){ "nginx" } replicas: (int){ 2 } name: (string){ "nginx" } } } } cue-lang-cue-db9cc73/cue/testdata/export/023.txtar000066400000000000000000000035251474664451600220030ustar00rootroot00000000000000raw: true -- in.cue -- { #emb: { a: 1 sub: { f: 3 } } #def: { #emb b: 2 } #f: a: 10 #e: { #f b: int {[_]: <100} {[_]: <300} } } -- out/def -- #emb: { a: 1 sub: { f: 3 } } #def: { b: 2 #emb } #f: { a: 10 } #e: { b: int #f [string]: <100 [string]: <300 } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/compile -- --- in.cue { { #emb: { a: 1 sub: { f: 3 } } #def: { 〈1;#emb〉 b: 2 } #f: { a: 10 } #e: { 〈1;#f〉 b: int { [_]: <100 } { [_]: <300 } } } } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 11 Allocs: 4 Retain: 0 Unifications: 15 Conjuncts: 26 Disjuncts: 15 -- out/evalalpha -- (struct){ #emb: (#struct){ a: (int){ 1 } sub: (#struct){ f: (int){ 3 } } } #def: (#struct){ b: (int){ 2 } a: (int){ 1 } sub: (#struct){ f: (int){ 3 } } } #f: (#struct){ a: (int){ 10 } } #e: (#struct){ b: (int){ &(<100, int) } a: (int){ 10 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -6,17 +6,17 @@ } } #def: (#struct){ - a: (int){ 1 } - sub: (#struct){ - f: (int){ 3 } - } b: (int){ 2 } + a: (int){ 1 } + sub: (#struct){ + f: (int){ 3 } + } } #f: (#struct){ a: (int){ 10 } } #e: (#struct){ - a: (int){ 10 } b: (int){ &(<100, int) } + a: (int){ 10 } } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ #emb: (#struct){ a: (int){ 1 } sub: (#struct){ f: (int){ 3 } } } #def: (#struct){ a: (int){ 1 } sub: (#struct){ f: (int){ 3 } } b: (int){ 2 } } #f: (#struct){ a: (int){ 10 } } #e: (#struct){ a: (int){ 10 } b: (int){ &(<100, int) } } } cue-lang-cue-db9cc73/cue/testdata/export/024.txtar000066400000000000000000000037511474664451600220050ustar00rootroot00000000000000raw: true eval: true noOpt: true -- in.cue -- { reg: {foo: 1, bar: {baz: 3}} #def: { a: 1 sub: reg } val: #def #def2: { a: {b: int} } val2: #def2 } -- out/def -- reg: { foo: 1 bar: { baz: 3 } } #def: { a: 1 sub: reg } val: #def #def2: { a: { b: int } } val2: #def2 -- out/compile -- --- in.cue { { reg: { foo: 1 bar: { baz: 3 } } #def: { a: 1 sub: 〈1;reg〉 } val: 〈0;#def〉 #def2: { a: { b: int } } val2: 〈0;#def2〉 } } -- out/eval/stats -- Leaks: 0 Freed: 23 Reused: 18 Allocs: 5 Retain: 0 Unifications: 23 Conjuncts: 28 Disjuncts: 23 -- out/evalalpha -- (struct){ reg: (struct){ foo: (int){ 1 } bar: (struct){ baz: (int){ 3 } } } #def: (#struct){ a: (int){ 1 } sub: (#struct){ foo: (int){ 1 } bar: (#struct){ baz: (int){ 3 } } } } val: ~(#def) #def2: (#struct){ a: (#struct){ b: (int){ int } } } val2: ~(#def2) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -14,23 +14,11 @@ } } } - val: (#struct){ - a: (int){ 1 } - sub: (#struct){ - foo: (int){ 1 } - bar: (#struct){ - baz: (int){ 3 } - } - } - } + val: ~(#def) #def2: (#struct){ a: (#struct){ b: (int){ int } } } - val2: (#struct){ - a: (#struct){ - b: (int){ int } - } - } + val2: ~(#def2) } -- out/eval -- (struct){ reg: (struct){ foo: (int){ 1 } bar: (struct){ baz: (int){ 3 } } } #def: (#struct){ a: (int){ 1 } sub: (#struct){ foo: (int){ 1 } bar: (#struct){ baz: (int){ 3 } } } } val: (#struct){ a: (int){ 1 } sub: (#struct){ foo: (int){ 1 } bar: (#struct){ baz: (int){ 3 } } } } #def2: (#struct){ a: (#struct){ b: (int){ int } } } val2: (#struct){ a: (#struct){ b: (int){ int } } } } cue-lang-cue-db9cc73/cue/testdata/export/025.txtar000066400000000000000000000013221474664451600217760ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { b: [{ {[X=_]: int} if a > 4 { f: 4 } }][a] a: int c: *1 | 2 } -- out/def -- b: [{ if a > 4 { f: 4 } {[X=string]: int} }][a] a: int c: *1 | 2 -- out/compile -- --- in.cue { { b: [ { { [_]: int } if (〈2;a〉 > 4) { f: 4 } }, ][〈0;a〉] a: int c: (*1|2) } } -- out/eval/stats -- Leaks: 5 Freed: 6 Reused: 2 Allocs: 9 Retain: 10 Unifications: 9 Conjuncts: 16 Disjuncts: 16 -- out/eval -- (struct){ b: (_|_){ // [incomplete] b: invalid non-ground value int (must be concrete int): // ./in.cue:8:5 } a: (int){ int } c: (int){ |(*(int){ 1 }, (int){ 2 }) } } cue-lang-cue-db9cc73/cue/testdata/export/026.txtar000066400000000000000000000006101474664451600217760ustar00rootroot00000000000000raw: true -- in.cue -- { if false { {a: 1} | {b: 1} } } -- out/def -- -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/compile -- --- in.cue { { if false { ({ a: 1 }|{ b: 1 }) } } } -- out/eval/stats -- Leaks: 0 Freed: 1 Reused: 0 Allocs: 1 Retain: 0 Unifications: 1 Conjuncts: 2 Disjuncts: 1 -- out/eval -- (struct){ } cue-lang-cue-db9cc73/cue/testdata/export/027.txtar000066400000000000000000000010071474664451600220000ustar00rootroot00000000000000 TODO: Should #Bar result in string or #Foo | string? raw: true eval: true -- in.cue -- { #Foo: { #Bar: #Foo | string } } -- out/def -- #Foo: { #Bar: #Foo | string } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/compile -- --- in.cue { { #Foo: { #Bar: (〈1;#Foo〉|string) } } } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 1 Allocs: 4 Retain: 0 Unifications: 3 Conjuncts: 6 Disjuncts: 5 -- out/eval -- (struct){ #Foo: (#struct){ #Bar: (string){ string } } } cue-lang-cue-db9cc73/cue/testdata/export/028.txtar000066400000000000000000000013661474664451600220110ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { #FindInMap: { #: "Fn::FindInMap": [string | #FindInMap] } a: [...string] } -- out/def -- #FindInMap: { #: { "Fn::FindInMap": [string | #FindInMap] } } a: [...string] -- out/export -- a: [] -- out/yaml -- a: [] -- out/json -- {"a":[]} -- out/compile -- --- in.cue { { #FindInMap: { #: { "Fn::FindInMap": [ (string|〈3;#FindInMap〉), ] } } a: [ ...string, ] } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 1 Allocs: 7 Retain: 0 Unifications: 6 Conjuncts: 9 Disjuncts: 8 -- out/eval -- (struct){ #FindInMap: (#struct){ #: (#struct){ "Fn::FindInMap": (#list){ 0: (string){ string } } } } a: (list){ } } cue-lang-cue-db9cc73/cue/testdata/export/029.txtar000066400000000000000000000017501474664451600220070ustar00rootroot00000000000000raw: true eval: true noOpt: true -- in.cue -- { #And: { #: "Fn::And": [...(3 | #And)] } #Ands: #And & { #: "Fn::And": [_] } } -- out/def -- #And: { #: { "Fn::And": [...3 | #And] } } #Ands: #And & { #: { "Fn::And": [_] } } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/compile -- --- in.cue { { #And: { #: { "Fn::And": [ ...(3|〈3;#And〉), ] } } #Ands: (〈0;#And〉 & { #: { "Fn::And": [ _, ] } }) } } -- out/eval/stats -- Leaks: 0 Freed: 12 Reused: 3 Allocs: 9 Retain: 0 Unifications: 10 Conjuncts: 19 Disjuncts: 12 -- out/eval -- (struct){ #And: (#struct){ #: (#struct){ "Fn::And": (list){ } } } #Ands: (#struct){ #: (#struct){ "Fn::And": (#list){ 0: ((int|struct)){ |((int){ 3 }, (#struct){ #: (#struct){ "Fn::And": (list){ } } }) } } } } } cue-lang-cue-db9cc73/cue/testdata/export/030.txtar000066400000000000000000000053531474664451600220020ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { #Foo: { sgl: #Bar ref: null | #Foo ext: #Bar | null ref: null | #Foo ref2: null | #Foo.sgl ... } #Foo: { "#Foo": 2 ... } #Bar: string } -- out/def -- #Foo: { "#Foo": 2 sgl: #Bar ref: (null | #Foo) & (null | #Foo) ext: #Bar | null ref2: null | #Foo.sgl ... } #Bar: string -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/compile -- --- in.cue { { #Foo: { sgl: 〈1;#Bar〉 ref: (null|〈1;#Foo〉) ext: (〈1;#Bar〉|null) ref: (null|〈1;#Foo〉) ref2: (null|〈1;#Foo〉.sgl) ... } #Foo: { "#Foo": 2 ... } #Bar: string } } -- out/evalalpha/stats -- Leaks: 15 Freed: 3 Reused: 3 Allocs: 15 Retain: 0 Unifications: 8 Conjuncts: 42 Disjuncts: 10 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 70 -Reused: 59 -Allocs: 11 -Retain: 1 +Leaks: 15 +Freed: 3 +Reused: 3 +Allocs: 15 +Retain: 0 -Unifications: 28 -Conjuncts: 131 -Disjuncts: 71 +Unifications: 8 +Conjuncts: 42 +Disjuncts: 10 -- out/eval/stats -- Leaks: 0 Freed: 70 Reused: 59 Allocs: 11 Retain: 1 Unifications: 28 Conjuncts: 131 Disjuncts: 71 -- out/evalalpha -- (struct){ #Foo: (#struct){ sgl: (string){ string } ref: (null){ null } ext: ((null|string)){ |((string){ string }, (null){ null }) } ref2: ((null|string)){ |((null){ null }, (string){ string }) } "#Foo": (int){ 2 } } #Bar: (string){ string } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,13 +1,7 @@ (struct){ #Foo: (#struct){ sgl: (string){ string } - ref: ((null|struct)){ |((null){ null }, (#struct){ - sgl: (string){ string } - ref: (null){ null } - ext: ((null|string)){ |((string){ string }, (null){ null }) } - ref2: ((null|string)){ |((null){ null }, (string){ string }) } - "#Foo": (int){ 2 } - }) } + ref: (null){ null } ext: ((null|string)){ |((string){ string }, (null){ null }) } ref2: ((null|string)){ |((null){ null }, (string){ string }) } "#Foo": (int){ 2 } -- diff/todo/p2 -- Structural cycle eliminated too soon? -- out/eval -- (struct){ #Foo: (#struct){ sgl: (string){ string } ref: ((null|struct)){ |((null){ null }, (#struct){ sgl: (string){ string } ref: (null){ null } ext: ((null|string)){ |((string){ string }, (null){ null }) } ref2: ((null|string)){ |((null){ null }, (string){ string }) } "#Foo": (int){ 2 } }) } ext: ((null|string)){ |((string){ string }, (null){ null }) } ref2: ((null|string)){ |((null){ null }, (string){ string }) } "#Foo": (int){ 2 } } #Bar: (string){ string } } cue-lang-cue-db9cc73/cue/testdata/export/031.txtar000066400000000000000000000010321474664451600217710ustar00rootroot00000000000000raw: true eval: true -- in.cue -- { A: [uint] B: A & ([10] | [192]) } -- out/def -- A: [>=0] B: A & ([10] | [192]) -- out/compile -- --- in.cue { { A: [ &(int, >=0), ] B: (〈0;A〉 & ([ 10, ]|[ 192, ])) } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 3 Allocs: 5 Retain: 0 Unifications: 6 Conjuncts: 13 Disjuncts: 8 -- out/eval -- (struct){ A: (#list){ 0: (int){ &(>=0, int) } } B: (list){ |((#list){ 0: (int){ 10 } }, (#list){ 0: (int){ 192 } }) } } cue-lang-cue-db9cc73/cue/testdata/export/032.txtar000066400000000000000000000005641474664451600220030ustar00rootroot00000000000000-- in.cue -- { [string]: _ foo: 3 } -- out/def -- foo: 3 ... -- out/export -- foo: 3 -- out/yaml -- foo: 3 -- out/json -- {"foo":3} -- out/compile -- --- in.cue { { [string]: _ foo: 3 } } -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 0 Unifications: 2 Conjuncts: 4 Disjuncts: 2 -- out/eval -- (struct){ foo: (int){ 3 } } cue-lang-cue-db9cc73/cue/testdata/export/issue2119.txtar000066400000000000000000000036631474664451600231470ustar00rootroot00000000000000-- in.cue -- import ( "encoding/yaml" "regexp" ) simplified: { x: d: R={ ".*" [R+""][0] } out: yaml.Marshal(x) } original: { #testableRegexp: R={ string #test: close({ in: string out: regexp.FindSubmatch("^"+R+"$", in)[1] }) } rule: { #patterns: { bar: #testableRegexp & { "(.*)" #test: {in: "testcontent", out: "testcontent"} } } } out: yaml.Marshal(rule) } -- out/eval/stats -- Leaks: 4 Freed: 17 Reused: 10 Allocs: 11 Retain: 4 Unifications: 21 Conjuncts: 39 Disjuncts: 21 -- out/eval -- (struct){ simplified: (struct){ x: (struct){ d: (string){ ".*" } } out: (string){ "d: .*\n" } } original: (struct){ #testableRegexp: (string){ string #test: (#struct){ in: (string){ string } out: (_|_){ // [incomplete] original.#testableRegexp.#test.out: non-concrete value string in operand to +: // ./in.cue:20:29 // ./in.cue:15:21 // ./in.cue:16:3 } } } rule: (struct){ #patterns: (#struct){ bar: (string){ "(.*)" #test: (#struct){ in: (string){ "testcontent" } out: (string){ "testcontent" } } } } } out: (string){ "{}\n" } } } -- out/compile -- --- in.cue { simplified: { x: { d: { ".*" [ (〈2〉 + ""), ][0] } } out: 〈import;"encoding/yaml"〉.Marshal(〈0;x〉) } original: { #testableRegexp: { string #test: close({ in: string out: 〈import;regexp〉.FindSubmatch((("^" + 〈2〉) + "$"), 〈0;in〉)[1] }) } rule: { #patterns: { bar: (〈2;#testableRegexp〉 & { "(.*)" #test: { in: "testcontent" out: "testcontent" } }) } } out: 〈import;"encoding/yaml"〉.Marshal(〈0;rule〉) } } cue-lang-cue-db9cc73/cue/testdata/export/issue2244.txtar000066400000000000000000000055361474664451600231470ustar00rootroot00000000000000-- in.cue -- package x import ( "strings" ) _#matchPattern: { #pattern: string [ // can't remove this builtin call if strings.HasSuffix(#pattern, "*") { // this let is required _within_ the if block // i.e. it can't be "inlined" with the if that // currently contains it let prefix = strings.TrimSuffix(#pattern, "*") prefix }, "'\(#pattern)'", ][0] } _#isReleaseTag: _#matchPattern & {#pattern: "refs/tags/v*", _} #step: { if: number | string } m: #step & { if: _#isReleaseTag } -- out/eval/stats -- Leaks: 16 Freed: 17 Reused: 13 Allocs: 20 Retain: 30 Unifications: 24 Conjuncts: 58 Disjuncts: 40 -- diff/explanation -- New evaluator should ultimately disallow new definitions in closed structs and not allow #pattern in #step -- out/evalalpha -- (struct){ _#matchPattern(:x): (_|_){ // [incomplete] error in call to strings.HasSuffix: non-concrete value string: // ./in.cue:11:6 // ./in.cue:8:12 #pattern: (string){ string } } _#isReleaseTag(:x): (string){ "refs/tags/v" #pattern: (string){ "refs/tags/v*" } let prefix#1 = (string){ "refs/tags/v" } } #step: (#struct){ if: ((string|number)){ |((number){ number }, (string){ string }) } } m: (#struct){ if: (string){ "refs/tags/v" #pattern: (string){ "refs/tags/v*" } let prefix#1 = (string){ "refs/tags/v" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,6 +1,6 @@ (struct){ _#matchPattern(:x): (_|_){ - // [incomplete] _#matchPattern: error in call to strings.HasSuffix: non-concrete value string: + // [incomplete] error in call to strings.HasSuffix: non-concrete value string: // ./in.cue:11:6 // ./in.cue:8:12 #pattern: (string){ string } -- out/eval -- (struct){ _#matchPattern(:x): (_|_){ // [incomplete] _#matchPattern: error in call to strings.HasSuffix: non-concrete value string: // ./in.cue:11:6 // ./in.cue:8:12 #pattern: (string){ string } } _#isReleaseTag(:x): (string){ "refs/tags/v" #pattern: (string){ "refs/tags/v*" } let prefix#1 = (string){ "refs/tags/v" } } #step: (#struct){ if: ((string|number)){ |((number){ number }, (string){ string }) } } m: (#struct){ if: (string){ "refs/tags/v" #pattern: (string){ "refs/tags/v*" } let prefix#1 = (string){ "refs/tags/v" } } } } -- out/compile -- --- in.cue { _#matchPattern: { #pattern: string [ if 〈import;strings〉.HasSuffix(〈1;#pattern〉, "*") { let prefix#1 = 〈import;strings〉.TrimSuffix(〈2;#pattern〉, "*") 〈0;let prefix#1〉 }, "'\(〈1;#pattern〉)'", ][0] } _#isReleaseTag: (〈0;_#matchPattern〉 & { #pattern: "refs/tags/v*" _ }) #step: { if: (number|string) } m: (〈0;#step〉 & { if: 〈1;_#isReleaseTag〉 }) } cue-lang-cue-db9cc73/cue/testdata/export/issue854.txtar000066400000000000000000000010431474664451600230610ustar00rootroot00000000000000-- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- a.cue -- package a import "mod.test/b" theb: b.name -- b/b.cue -- package b import "mod.test/c" b: c.c & { other: "name" } name: b.other -- c/c.cue -- package c -- out/compile -- --- a.cue { theb: 〈import;"mod.test/b"〉.name } -- out/eval/stats -- Leaks: 4 Freed: 2 Reused: 0 Allocs: 6 Retain: 8 Unifications: 6 Conjuncts: 8 Disjuncts: 8 -- out/eval -- (struct){ theb: (_|_){ // [incomplete] b: undefined field: c: // ./b/b.cue:5:6 } } cue-lang-cue-db9cc73/cue/testdata/fulleval/000077500000000000000000000000001474664451600206775ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/fulleval/000_detect_conflicting_value.txtar000066400000000000000000000021061474664451600273640ustar00rootroot00000000000000#name: detect conflicting value #evalFull -- in.cue -- a: 8000.9 a: 7080 | int -- out/def -- a: _|_ // conflicting values 8000.9 and int (mismatched types float and int) -- out/legacy-debug -- <0>{a: _|_((8000.9 & (int | int)):conflicting values 8000.9 and int (mismatched types float and int))} -- out/compile -- --- in.cue { a: 8000.9 a: (7080|int) } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 1 Allocs: 3 Retain: 0 Unifications: 2 Conjuncts: 5 Disjuncts: 4 -- out/eval -- Errors: a: 2 errors in empty disjunction: a: conflicting values 8000.9 and 7080 (mismatched types float and int): ./in.cue:1:4 ./in.cue:2:4 a: conflicting values 8000.9 and int (mismatched types float and int): ./in.cue:1:4 ./in.cue:2:11 Result: (_|_){ // [eval] a: (_|_){ // [eval] a: 2 errors in empty disjunction: // a: conflicting values 8000.9 and 7080 (mismatched types float and int): // ./in.cue:1:4 // ./in.cue:2:4 // a: conflicting values 8000.9 and int (mismatched types float and int): // ./in.cue:1:4 // ./in.cue:2:11 } } cue-lang-cue-db9cc73/cue/testdata/fulleval/001_conflicts_in_optional_fields_are_okay_.txtar000066400000000000000000000033651474664451600322700ustar00rootroot00000000000000#name: conflicts in optional fields are okay #evalFull -- in.cue -- d: {a: 1, b?: 3} | {a: 2} // the following conjunction should not eliminate any disjuncts c: d & {b?: 4} -- out/def -- d: { a: 1 b?: 3 } | { a: 2 } // the following conjunction should not eliminate any disjuncts c: d & { b?: 4 } -- out/legacy-debug -- <0>{d: (<1>{a: 1, b?: 3} | <2>{a: 2}), c: (<3>{a: 1, b?: (3 & 4)} | <4>{a: 2, b?: 4})} -- out/compile -- --- in.cue { d: ({ a: 1 b?: 3 }|{ a: 2 }) c: (〈0;d〉 & { b?: 4 }) } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 9 Allocs: 5 Retain: 0 Unifications: 10 Conjuncts: 17 Disjuncts: 14 -- out/evalalpha -- (struct){ d: (struct){ |((struct){ a: (int){ 1 } b?: (int){ 3 } }, (struct){ a: (int){ 2 } }) } c: (struct){ |((struct){ b?: (_|_){ // [eval] c.b: conflicting values 3 and 4: // ./in.cue:1:15 // ./in.cue:4:13 } a: (int){ 1 } }, (struct){ b?: (int){ 4 } a: (int){ 2 } }) } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -9,7 +9,6 @@ b?: (_|_){ // [eval] c.b: conflicting values 3 and 4: // ./in.cue:1:15 - // ./in.cue:4:4 // ./in.cue:4:13 } a: (int){ 1 } -- diff/todo/p3 -- Missing error position. -- out/eval -- (struct){ d: (struct){ |((struct){ a: (int){ 1 } b?: (int){ 3 } }, (struct){ a: (int){ 2 } }) } c: (struct){ |((struct){ b?: (_|_){ // [eval] c.b: conflicting values 3 and 4: // ./in.cue:1:15 // ./in.cue:4:4 // ./in.cue:4:13 } a: (int){ 1 } }, (struct){ b?: (int){ 4 } a: (int){ 2 } }) } } cue-lang-cue-db9cc73/cue/testdata/fulleval/002_resolve_all_disjunctions.txtar000066400000000000000000000035431474664451600274540ustar00rootroot00000000000000#name: resolve all disjunctions #evalFull -- in.cue -- service: [Name=string]: { name: string | *Name port: int | *7080 } service: foo: _ service: bar: {port: 8000} service: baz: {name: "foobar"} -- out/def -- service: { {[Name=string]: { name: string | *Name, port: int | *7080 }} foo: { name: string | *"foo" port: int | *7080 } bar: { name: string | *"bar" port: 8000 } baz: { name: "foobar" port: int | *7080 } } -- out/export -- service: { foo: { name: "foo" port: 7080 } bar: { name: "bar" port: 8000 } baz: { name: "foobar" port: 7080 } } -- out/yaml -- service: foo: name: foo port: 7080 bar: name: bar port: 8000 baz: name: foobar port: 7080 -- out/json -- {"service":{"foo":{"name":"foo","port":7080},"bar":{"name":"bar","port":8000},"baz":{"name":"foobar","port":7080}}} -- out/legacy-debug -- <0>{service: <1>{[]: <2>(Name: string)-><3>{name: (string | *<2>.Name), port: (int | *7080)}, foo: <4>{name: "foo", port: 7080}, bar: <5>{name: "bar", port: 8000}, baz: <6>{name: "foobar", port: 7080}}} -- out/compile -- --- in.cue { service: { [string]: { name: (string|*〈1;-〉) port: (int|*7080) } } service: { foo: _ } service: { bar: { port: 8000 } } service: { baz: { name: "foobar" } } } -- out/eval/stats -- Leaks: 0 Freed: 23 Reused: 17 Allocs: 6 Retain: 0 Unifications: 11 Conjuncts: 31 Disjuncts: 23 -- out/eval -- (struct){ service: (struct){ foo: (struct){ name: (string){ |(*(string){ "foo" }, (string){ string }) } port: (int){ |(*(int){ 7080 }, (int){ int }) } } bar: (struct){ port: (int){ 8000 } name: (string){ |(*(string){ "bar" }, (string){ string }) } } baz: (struct){ name: (string){ "foobar" } port: (int){ |(*(int){ 7080 }, (int){ int }) } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/003_field_templates.txtar000066400000000000000000000040301474664451600255030ustar00rootroot00000000000000#name: field templates #evalFull -- in.cue -- a: { {[name=_]: int} k: 1 } b: { {[X=_]: {x: 0, y: *1 | int}} v: {} w: {y: 0} } b: {[y=_]: {}} // TODO: allow different name c: { {[Name=_]: {name: Name, y: 1}} foo: {} bar: _ } -- out/def -- a: { {[name=string]: int} k: 1 } b: { {[X=string]: { x: 0, y: *1 | int }} v: { x: 0 y: *1 | int } w: { x: 0 y: 0 } } c: { {[Name=string]: { y: 1, name: Name }} foo: { y: 1 name: "foo" } bar: { y: 1 name: "bar" } } -- out/export -- a: { k: 1 } b: { v: { x: 0 y: 1 } w: { x: 0 y: 0 } } c: { foo: { y: 1 name: "foo" } bar: { y: 1 name: "bar" } } -- out/yaml -- a: k: 1 b: v: x: 0 y: 1 w: x: 0 y: 0 c: foo: y: 1 name: foo bar: y: 1 name: bar -- out/json -- {"a":{"k":1},"b":{"v":{"x":0,"y":1},"w":{"x":0,"y":0}},"c":{"foo":{"y":1,"name":"foo"},"bar":{"y":1,"name":"bar"}}} -- out/legacy-debug -- <0>{a: <1>{[]: <2>(name: string)->int, k: 1}, b: <3>{[]: <4>(X: string)->(<5>{x: 0, y: (*1 | int)} & <6>{}), v: <7>{x: 0, y: 1}, w: <8>{x: 0, y: 0}}, c: <9>{[]: <10>(Name: string)-><11>{y: 1, name: <10>.Name}, foo: <12>{y: 1, name: "foo"}, bar: <13>{y: 1, name: "bar"}}} -- out/compile -- --- in.cue { a: { { [_]: int } k: 1 } b: { { [_]: { x: 0 y: (*1|int) } } v: {} w: { y: 0 } } b: { [_]: {} } c: { { [_]: { name: 〈1;-〉 y: 1 } } foo: {} bar: _ } } -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 15 Allocs: 6 Retain: 0 Unifications: 17 Conjuncts: 33 Disjuncts: 21 -- out/eval -- (struct){ a: (struct){ k: (int){ 1 } } b: (struct){ v: (struct){ x: (int){ 0 } y: (int){ |(*(int){ 1 }, (int){ int }) } } w: (struct){ y: (int){ 0 } x: (int){ 0 } } } c: (struct){ foo: (struct){ name: (string){ "foo" } y: (int){ 1 } } bar: (struct){ name: (string){ "bar" } y: (int){ 1 } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/004_field_comprehension.txtar000066400000000000000000000024551474664451600263700ustar00rootroot00000000000000#name: field comprehension #evalFull -- in.cue -- a: { for k, v in b if k < "d" if v > b.a { "\(k)": v } } b: { a: 1 b: 2 c: 3 d: 4 } c: { for k, v in b if k < "d" if v > b.a { "\(k)": v } } -- out/def -- a: { b: 2 c: 3 } b: { a: 1 b: 2 c: 3 d: 4 } c: { b: 2 c: 3 } -- out/export -- a: { b: 2 c: 3 } b: { a: 1 b: 2 c: 3 d: 4 } c: { b: 2 c: 3 } -- out/yaml -- a: b: 2 c: 3 b: a: 1 b: 2 c: 3 d: 4 c: b: 2 c: 3 -- out/json -- {"a":{"b":2,"c":3},"b":{"a":1,"b":2,"c":3,"d":4},"c":{"b":2,"c":3}} -- out/legacy-debug -- <0>{a: <1>{b: 2, c: 3}, b: <2>{a: 1, b: 2, c: 3, d: 4}, c: <3>{b: 2, c: 3}} -- out/compile -- --- in.cue { a: { for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { "\(〈1;k〉)": 〈1;v〉 } } b: { a: 1 b: 2 c: 3 d: 4 } c: { for k, v in 〈1;b〉 if (〈0;k〉 < "d") if (〈0;v〉 > 〈2;b〉.a) { "\(〈1;k〉)": 〈1;v〉 } } } -- out/eval/stats -- Leaks: 0 Freed: 12 Reused: 5 Allocs: 7 Retain: 12 Unifications: 12 Conjuncts: 17 Disjuncts: 16 -- out/eval -- (struct){ a: (struct){ b: (int){ 2 } c: (int){ 3 } } b: (struct){ a: (int){ 1 } b: (int){ 2 } c: (int){ 3 } d: (int){ 4 } } c: (struct){ b: (int){ 2 } c: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/005_conditional_field.txtar000066400000000000000000000015031474664451600260140ustar00rootroot00000000000000#name: conditional field #evalFull -- in.cue -- if b { a: "foo" } b: true c: { a: 3 if a > 1 { a: 3 } } d: { a: int if a > 1 { a: 3 } } -- out/def -- b: true a: "foo" c: { a: 3 } d: { a: int if a > 1 { a: 3 } } -- out/legacy-debug -- <0>{b: true, a: "foo", c: <1>{a: 3}, d: <2>{a: int if (<3>.a > 1) yield <4>{a: 3}}} -- out/compile -- --- in.cue { if 〈0;b〉 { a: "foo" } b: true c: { a: 3 if (〈0;a〉 > 1) { a: 3 } } d: { a: int if (〈0;a〉 > 1) { a: 3 } } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 4 Allocs: 3 Retain: 1 Unifications: 7 Conjuncts: 7 Disjuncts: 7 -- out/eval -- (struct){ a: (string){ "foo" } b: (bool){ true } c: (struct){ a: (int){ 3 } } d: (_|_){ // [cycle] cycle error: // ./in.cue:14:5 } } cue-lang-cue-db9cc73/cue/testdata/fulleval/006_referencing_field_in_field_comprehension.txtar000066400000000000000000000015351474664451600325700ustar00rootroot00000000000000#name: referencing field in field comprehension #evalFull -- in.cue -- a: {b: c: 4} a: { b: d: 5 for k, v in b { "\(k)": v } } -- out/def -- a: { b: { c: 4 d: 5 } c: 4 d: 5 } -- out/export -- a: { b: { c: 4 d: 5 } c: 4 d: 5 } -- out/yaml -- a: b: c: 4 d: 5 c: 4 d: 5 -- out/json -- {"a":{"b":{"c":4,"d":5},"c":4,"d":5}} -- out/legacy-debug -- <0>{a: <1>{b: <2>{c: 4, d: 5}, c: 4, d: 5}} -- out/compile -- --- in.cue { a: { b: { c: 4 } } a: { b: { d: 5 } for k, v in 〈0;b〉 { "\(〈1;k〉)": 〈1;v〉 } } } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 3 Allocs: 4 Retain: 1 Unifications: 7 Conjuncts: 13 Disjuncts: 8 -- out/eval -- (struct){ a: (struct){ b: (struct){ c: (int){ 4 } d: (int){ 5 } } c: (int){ 4 } d: (int){ 5 } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/007_different_labels_for_templates.txtar000066400000000000000000000015141474664451600305660ustar00rootroot00000000000000#name: different labels for templates #evalFull -- in.cue -- a: [X=string]: {name: X} a: [Name=string]: {name: Name} a: foo: {} -- out/def -- a: { {[X=string]: { name: X & X }} foo: { name: "foo" } } -- out/export -- a: { foo: { name: "foo" } } -- out/yaml -- a: foo: name: foo -- out/json -- {"a":{"foo":{"name":"foo"}}} -- out/legacy-debug -- <0>{a: <1>{[]: <2>(X: string)->(<3>{name: <2>.X} & <4>{name: <2>.X}), foo: <5>{name: "foo"}}} -- out/compile -- --- in.cue { a: { [string]: { name: 〈1;-〉 } } a: { [string]: { name: 〈1;-〉 } } a: { foo: {} } } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 0 Allocs: 4 Retain: 0 Unifications: 4 Conjuncts: 9 Disjuncts: 4 -- out/eval -- (struct){ a: (struct){ foo: (struct){ name: (string){ "foo" } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/008_nested_templates_in_one_field.txtar000066400000000000000000000051351474664451600304100ustar00rootroot00000000000000#name: nested templates in one field #evalFull -- in.cue -- a: [A=string]: b: [B=string]: { name: A kind: B } a: "A": b: "B": _ a: "C": b: "D": _ a: "EE": b: "FF": {c: "bar"} -- out/def -- a: { {[A=string]: { b: { [B=string]: { name: A, kind: B } } }} A: { b: { {[B=string]: { name: "A", kind: B }} B: { name: "A" kind: "B" } } } C: { b: { {[B=string]: { name: "C", kind: B }} D: { name: "C" kind: "D" } } } EE: { b: { {[B=string]: { name: "EE", kind: B }} FF: { name: "EE" kind: "FF" c: "bar" } } } } -- out/export -- a: { A: { b: { B: { name: "A" kind: "B" } } } C: { b: { D: { name: "C" kind: "D" } } } EE: { b: { FF: { name: "EE" kind: "FF" c: "bar" } } } } -- out/yaml -- a: A: b: B: name: A kind: B C: b: D: name: C kind: D EE: b: FF: name: EE kind: FF c: bar -- out/json -- {"a":{"A":{"b":{"B":{"name":"A","kind":"B"}}},"C":{"b":{"D":{"name":"C","kind":"D"}}},"EE":{"b":{"FF":{"name":"EE","kind":"FF","c":"bar"}}}}} -- out/legacy-debug -- <0>{a: <1>{[]: <2>(A: string)-><3>{b: <4>{[]: <5>(B: string)-><6>{name: <2>.A, kind: <5>.B}, }}, A: <7>{b: <8>{[]: <9>(B: string)-><10>{name: <11>.A, kind: <9>.B}, B: <12>{name: "A", kind: "B"}}}, C: <13>{b: <14>{[]: <15>(B: string)-><16>{name: <17>.A, kind: <15>.B}, D: <18>{name: "C", kind: "D"}}}, EE: <19>{b: <20>{[]: <21>(B: string)-><22>{name: <23>.A, kind: <21>.B}, FF: <24>{name: "EE", kind: "FF", c: "bar"}}}}} -- out/compile -- --- in.cue { a: { [string]: { b: { [string]: { name: 〈3;-〉 kind: 〈1;-〉 } } } } a: { A: { b: { B: _ } } } a: { C: { b: { D: _ } } } a: { EE: { b: { FF: { c: "bar" } } } } } -- out/eval/stats -- Leaks: 0 Freed: 18 Reused: 12 Allocs: 6 Retain: 0 Unifications: 18 Conjuncts: 30 Disjuncts: 18 -- out/eval -- (struct){ a: (struct){ A: (struct){ b: (struct){ B: (struct){ name: (string){ "A" } kind: (string){ "B" } } } } C: (struct){ b: (struct){ D: (struct){ name: (string){ "C" } kind: (string){ "D" } } } } EE: (struct){ b: (struct){ FF: (struct){ c: (string){ "bar" } name: (string){ "EE" } kind: (string){ "FF" } } } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/009_template_unification_within_one_struct.txtar000066400000000000000000000031271474664451600324100ustar00rootroot00000000000000#name: template unification within one struct #evalFull -- in.cue -- a: { {[A=string]: {name: A}} // TODO: allow duplicate alias here {[X=string]: {kind: X}} } a: "A": _ a: "C": _ a: "E": {c: "bar"} -- out/def -- a: { {[A=string]: { name: A, kind: A }} E: { name: "E" kind: "E" c: "bar" } A: { name: "A" kind: "A" } C: { name: "C" kind: "C" } } -- out/export -- a: { E: { name: "E" kind: "E" c: "bar" } A: { name: "A" kind: "A" } C: { name: "C" kind: "C" } } -- out/yaml -- a: E: name: E kind: E c: bar A: name: A kind: A C: name: C kind: C -- out/json -- {"a":{"E":{"name":"E","kind":"E","c":"bar"},"A":{"name":"A","kind":"A"},"C":{"name":"C","kind":"C"}}} -- out/legacy-debug -- <0>{a: <1>{[]: <2>(A: string)->(<3>{name: <2>.A} & <4>{kind: <2>.A}), E: <5>{name: "E", kind: "E", c: "bar"}, A: <6>{name: "A", kind: "A"}, C: <7>{name: "C", kind: "C"}}} -- out/compile -- --- in.cue { a: { { [string]: { name: 〈1;-〉 } } { [string]: { kind: 〈1;-〉 } } } a: { A: _ } a: { C: _ } a: { E: { c: "bar" } } } -- out/eval/stats -- Leaks: 0 Freed: 12 Reused: 8 Allocs: 4 Retain: 0 Unifications: 12 Conjuncts: 23 Disjuncts: 12 -- out/eval -- (struct){ a: (struct){ A: (struct){ name: (string){ "A" } kind: (string){ "A" } } C: (struct){ name: (string){ "C" } kind: (string){ "C" } } E: (struct){ c: (string){ "bar" } name: (string){ "E" } kind: (string){ "E" } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/010_field_comprehensions_with_multiple_keys.txtar000066400000000000000000000053231474664451600325460ustar00rootroot00000000000000#name: field comprehensions with multiple keys #evalFull -- in.cue -- for x in [ {a: "A", b: "B"}, {a: "C", b: "D"}, {a: "E", b: "F"}, ] { a: "\(x.a)": b: "\(x.b)": x } for x in [ {a: "A", b: "B"}, {a: "C", b: "D"}, {a: "E", b: "F"}, ] { "\(x.a)": "\(x.b)": x } -- out/def -- E: { F: x } a: { E: { b: { F: x } } A: { b: { B: x } } C: { b: { D: x } } } A: { B: x } C: { D: x } -- out/export -- E: { F: { a: "E" b: "F" } } a: { E: { b: { F: { a: "E" b: "F" } } } A: { b: { B: { a: "A" b: "B" } } } C: { b: { D: { a: "C" b: "D" } } } } A: { B: { a: "A" b: "B" } } C: { D: { a: "C" b: "D" } } -- out/yaml -- E: F: a: E b: F a: E: b: F: a: E b: F A: b: B: a: A b: B C: b: D: a: C b: D A: B: a: A b: B C: D: a: C b: D -- out/json -- {"E":{"F":{"a":"E","b":"F"}},"a":{"E":{"b":{"F":{"a":"E","b":"F"}}},"A":{"b":{"B":{"a":"A","b":"B"}}},"C":{"b":{"D":{"a":"C","b":"D"}}}},"A":{"B":{"a":"A","b":"B"}},"C":{"D":{"a":"C","b":"D"}}} -- out/legacy-debug -- <0>{E: <1>{F: <2>{a: "E", b: "F"}}, a: <3>{E: <4>{b: <5>{F: <6>{a: "E", b: "F"}}}, A: <7>{b: <8>{B: <9>{a: "A", b: "B"}}}, C: <10>{b: <11>{D: <12>{a: "C", b: "D"}}}}, A: <13>{B: <14>{a: "A", b: "B"}}, C: <15>{D: <16>{a: "C", b: "D"}}} -- out/compile -- --- in.cue { for _, x in [ { a: "A" b: "B" }, { a: "C" b: "D" }, { a: "E" b: "F" }, ] { a: { "\(〈2;x〉.a)": { b: { "\(〈4;x〉.b)": 〈4;x〉 } } } } for _, x in [ { a: "A" b: "B" }, { a: "C" b: "D" }, { a: "E" b: "F" }, ] { "\(〈1;x〉.a)": { "\(〈2;x〉.b)": 〈2;x〉 } } } -- out/eval/stats -- Leaks: 20 Freed: 29 Reused: 25 Allocs: 24 Retain: 56 Unifications: 49 Conjuncts: 48 Disjuncts: 61 -- out/eval -- (struct){ a: (struct){ A: (struct){ b: (struct){ B: (struct){ a: (string){ "A" } b: (string){ "B" } } } } C: (struct){ b: (struct){ D: (struct){ a: (string){ "C" } b: (string){ "D" } } } } E: (struct){ b: (struct){ F: (struct){ a: (string){ "E" } b: (string){ "F" } } } } } A: (struct){ B: (struct){ a: (string){ "A" } b: (string){ "B" } } } C: (struct){ D: (struct){ a: (string){ "C" } b: (string){ "D" } } } E: (struct){ F: (struct){ a: (string){ "E" } b: (string){ "F" } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/011_field_comprehensions_with_templates.txtar000066400000000000000000000026001474664451600316520ustar00rootroot00000000000000#name: field comprehensions with templates #evalFull -- in.cue -- num: 1 a: { if num < 5 { [A=string]: [B=string]: { name: A kind: B } } } a: b: c: d: "bar" -- out/def -- num: 1 a: { {[A=string]: { [B=string]: { name: A, kind: B } }} b: { {[B=string]: { name: "b", kind: B }} c: { name: "b" kind: "c" d: "bar" } } } -- out/export -- num: 1 a: { b: { c: { name: "b" kind: "c" d: "bar" } } } -- out/yaml -- num: 1 a: b: c: name: b kind: c d: bar -- out/json -- {"num":1,"a":{"b":{"c":{"name":"b","kind":"c","d":"bar"}}}} -- out/legacy-debug -- <0>{num: 1, a: <1>{[]: <2>(A: string)-><3>{[]: <4>(B: string)-><5>{name: <2>.A, kind: <4>.B}, }, b: <6>{[]: <7>(B: string)-><8>{name: <9>.A, kind: <7>.B}, c: <10>{name: "b", kind: "c", d: "bar"}}}} -- out/compile -- --- in.cue { num: 1 a: { if (〈1;num〉 < 5) { [string]: { [string]: { name: 〈2;-〉 kind: 〈1;-〉 } } } } a: { b: { c: { d: "bar" } } } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 3 Allocs: 5 Retain: 0 Unifications: 8 Conjuncts: 12 Disjuncts: 8 -- out/eval -- (struct){ num: (int){ 1 } a: (struct){ b: (struct){ c: (struct){ d: (string){ "bar" } name: (string){ "b" } kind: (string){ "c" } } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/012_disjunctions_of_lists.txtar000066400000000000000000000015511474664451600267650ustar00rootroot00000000000000#name: disjunctions of lists #evalFull -- in.cue -- l: *[ int, int] | [ string, string] l1: ["a", "b"] l2: l & ["c", "d"] -- out/def -- l: *[int, int] | [string, string] l1: ["a", "b"] l2: ["c", "d"] -- out/legacy-debug -- <0>{l: [int,int], l1: ["a","b"], l2: ["c","d"]} -- out/compile -- --- in.cue { l: (*[ int, int, ]|[ string, string, ]) l1: [ "a", "b", ] l2: (〈0;l〉 & [ "c", "d", ]) } -- out/eval/stats -- Leaks: 0 Freed: 18 Reused: 13 Allocs: 5 Retain: 0 Unifications: 14 Conjuncts: 24 Disjuncts: 18 -- out/eval -- (struct){ l: (list){ |(*(#list){ 0: (int){ int } 1: (int){ int } }, (#list){ 0: (string){ string } 1: (string){ string } }) } l1: (#list){ 0: (string){ "a" } 1: (string){ "b" } } l2: (#list){ 0: (string){ "c" } 1: (string){ "d" } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/013_normalization.txtar000066400000000000000000000013501474664451600252330ustar00rootroot00000000000000TODO: the new evaluator currently does not normalize disjuncts. It needs to be determined under which circumstances is desirable. The redundancy that remains from not normalizing can be useful. #name: normalization #evalFull -- in.cue -- a: string | string b: *1 | *int c: *1.0 | *float -- out/def -- a: string b: int c: float -- out/legacy-debug -- <0>{a: string, b: int, c: float} -- out/compile -- --- in.cue { a: (string|string) b: (*1|*int) c: (*1.0|*float) } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 6 Allocs: 4 Retain: 0 Unifications: 4 Conjuncts: 10 Disjuncts: 10 -- out/eval -- (struct){ a: (string){ string } b: (int){ |(*(int){ 1 }, *(int){ int }) } c: (float){ |(*(float){ 1.0 }, *(float){ float }) } } cue-lang-cue-db9cc73/cue/testdata/fulleval/014_default_disambiguation_and_elimination.txtar000066400000000000000000000013421474664451600322640ustar00rootroot00000000000000#name: default disambiguation and elimination #evalFull -- in.cue -- a: *1 | int b: *3 | int c: a & b d: b & a e: *1 | *1 -- out/def -- a: *1 | int b: *3 | int c: a & b d: b & a e: 1 -- out/legacy-debug -- <0>{a: 1, b: 3, c: int, d: int, e: 1} -- out/compile -- --- in.cue { a: (*1|int) b: (*3|int) c: (〈0;a〉 & 〈0;b〉) d: (〈0;b〉 & 〈0;a〉) e: (*1|*1) } -- out/eval/stats -- Leaks: 0 Freed: 24 Reused: 17 Allocs: 7 Retain: 0 Unifications: 6 Conjuncts: 30 Disjuncts: 24 -- out/eval -- (struct){ a: (int){ |(*(int){ 1 }, (int){ int }) } b: (int){ |(*(int){ 3 }, (int){ int }) } c: (int){ |((int){ 1 }, (int){ 3 }, (int){ int }) } d: (int){ |((int){ 3 }, (int){ 1 }, (int){ int }) } e: (int){ 1 } } cue-lang-cue-db9cc73/cue/testdata/fulleval/016_struct_comprehension_with_template.txtar000066400000000000000000000072011474664451600315540ustar00rootroot00000000000000#name: struct comprehension with template #evalFull -- in.cue -- result: [for _, v in service {v}] service: [Name=string]: { name: *Name | string type: "service" port: *7080 | int } service: foo: {} service: bar: {port: 8000} service: baz: {name: "foobar"} -- out/def -- result: [{ name: *"foo" | string type: "service" port: *7080 | int }, { name: *"bar" | string type: "service" port: 8000 }, { name: "foobar" type: "service" port: *7080 | int }] service: { {[Name=string]: { name: *Name | string, type: "service", port: *7080 | int }} foo: { name: *"foo" | string type: "service" port: *7080 | int } bar: { name: *"bar" | string type: "service" port: 8000 } baz: { name: "foobar" type: "service" port: *7080 | int } } -- out/export -- result: [{ name: "foo" type: "service" port: 7080 }, { name: "bar" type: "service" port: 8000 }, { name: "foobar" type: "service" port: 7080 }] service: { foo: { name: "foo" type: "service" port: 7080 } bar: { name: "bar" type: "service" port: 8000 } baz: { name: "foobar" type: "service" port: 7080 } } -- out/yaml -- result: - name: foo type: service port: 7080 - name: bar type: service port: 8000 - name: foobar type: service port: 7080 service: foo: name: foo type: service port: 7080 bar: name: bar type: service port: 8000 baz: name: foobar type: service port: 7080 -- out/json -- {"result":[{"name":"foo","type":"service","port":7080},{"name":"bar","type":"service","port":8000},{"name":"foobar","type":"service","port":7080}],"service":{"foo":{"name":"foo","type":"service","port":7080},"bar":{"name":"bar","type":"service","port":8000},"baz":{"name":"foobar","type":"service","port":7080}}} -- out/legacy-debug -- <0>{result: [<1>{name: "foo", type: "service", port: 7080},<2>{name: "bar", type: "service", port: 8000},<3>{name: "foobar", type: "service", port: 7080}], service: <4>{[]: <5>(Name: string)-><6>{name: (*<5>.Name | string), type: "service", port: (*7080 | int)}, foo: <7>{name: "foo", type: "service", port: 7080}, bar: <8>{name: "bar", type: "service", port: 8000}, baz: <9>{name: "foobar", type: "service", port: 7080}}} -- out/compile -- --- in.cue { result: [ for _, v in 〈1;service〉 { 〈1;v〉 }, ] service: { [string]: { name: (*〈1;-〉|string) type: "service" port: (*7080|int) } } service: { foo: {} } service: { bar: { port: 8000 } } service: { baz: { name: "foobar" } } } -- out/eval/stats -- Leaks: 0 Freed: 51 Reused: 43 Allocs: 8 Retain: 4 Unifications: 27 Conjuncts: 70 Disjuncts: 55 -- out/eval -- (struct){ result: (#list){ 0: (struct){ name: (string){ |(*(string){ "foo" }, (string){ string }) } type: (string){ "service" } port: (int){ |(*(int){ 7080 }, (int){ int }) } } 1: (struct){ port: (int){ 8000 } name: (string){ |(*(string){ "bar" }, (string){ string }) } type: (string){ "service" } } 2: (struct){ name: (string){ "foobar" } type: (string){ "service" } port: (int){ |(*(int){ 7080 }, (int){ int }) } } } service: (struct){ foo: (struct){ name: (string){ |(*(string){ "foo" }, (string){ string }) } type: (string){ "service" } port: (int){ |(*(int){ 7080 }, (int){ int }) } } bar: (struct){ port: (int){ 8000 } name: (string){ |(*(string){ "bar" }, (string){ string }) } type: (string){ "service" } } baz: (struct){ name: (string){ "foobar" } type: (string){ "service" } port: (int){ |(*(int){ 7080 }, (int){ int }) } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/017_resolutions_in_struct_comprehension_keys.txtar000066400000000000000000000011241474664451600330140ustar00rootroot00000000000000#name: resolutions in struct comprehension keys #evalFull -- in.cue -- a: {for _, b in ["c"] {"\(b+".")": "a"}} -- out/def -- a: { "c.": "a" } -- out/export -- a: { "c.": "a" } -- out/yaml -- a: c.: a -- out/json -- {"a":{"c.":"a"}} -- out/legacy-debug -- <0>{a: <1>{"c.": "a"}} -- out/compile -- --- in.cue { a: { for _, b in [ "c", ] { "\((〈1;b〉 + "."))": "a" } } } -- out/eval/stats -- Leaks: 2 Freed: 3 Reused: 0 Allocs: 5 Retain: 3 Unifications: 5 Conjuncts: 5 Disjuncts: 4 -- out/eval -- (struct){ a: (struct){ "c.": (string){ "a" } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/018_recursive_evaluation_within_list.txtar000066400000000000000000000051061474664451600312300ustar00rootroot00000000000000#name: recursive evaluation within list #evalFull -- in.cue -- l: [a] a: b & {c: "t"} b: { d: c c: string } l1: [a1] a1: b1 & {c: "t"} b1: { d: "s" + c c: string } -- out/def -- l: [a] a: b & { c: "t" } b: { c: string d: c } l1: [a1] a1: b1 & { c: "t" } b1: { c: string d: "s" + c } -- out/legacy-debug -- <0>{l: [<1>{c: "t", d: "t"}], a: <2>{c: "t", d: "t"}, b: <3>{c: string, d: string}, l1: [<4>{c: "t", d: "st"}], a1: <5>{c: "t", d: "st"}, b1: <6>{c: string, d: ("s" + <7>.c)}} -- out/compile -- --- in.cue { l: [ 〈1;a〉, ] a: (〈0;b〉 & { c: "t" }) b: { d: 〈0;c〉 c: string } l1: [ 〈1;a1〉, ] a1: (〈0;b1〉 & { c: "t" }) b1: { d: ("s" + 〈0;c〉) c: string } } -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 14 Allocs: 7 Retain: 14 Unifications: 21 Conjuncts: 40 Disjuncts: 31 -- out/evalalpha -- (struct){ l: (#list){ 0: ~(a) } a: (struct){ c: (string){ "t" } d: (string){ "t" } } b: (struct){ d: (string){ string } c: (string){ string } } l1: (#list){ 0: ~(a1) } a1: (struct){ c: (string){ "t" } d: (string){ "st" } } b1: (struct){ d: (_|_){ // [incomplete] b1.d: non-concrete value string in operand to +: // ./in.cue:10:5 // ./in.cue:11:5 } c: (string){ string } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,13 +1,10 @@ (struct){ l: (#list){ - 0: (struct){ - d: (string){ "t" } - c: (string){ "t" } - } + 0: ~(a) } a: (struct){ + c: (string){ "t" } d: (string){ "t" } - c: (string){ "t" } } b: (struct){ d: (string){ string } @@ -14,14 +11,11 @@ c: (string){ string } } l1: (#list){ - 0: (struct){ - d: (string){ "st" } - c: (string){ "t" } - } + 0: ~(a1) } a1: (struct){ + c: (string){ "t" } d: (string){ "st" } - c: (string){ "t" } } b1: (struct){ d: (_|_){ -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ l: (#list){ 0: (struct){ d: (string){ "t" } c: (string){ "t" } } } a: (struct){ d: (string){ "t" } c: (string){ "t" } } b: (struct){ d: (string){ string } c: (string){ string } } l1: (#list){ 0: (struct){ d: (string){ "st" } c: (string){ "t" } } } a1: (struct){ d: (string){ "st" } c: (string){ "t" } } b1: (struct){ d: (_|_){ // [incomplete] b1.d: non-concrete value string in operand to +: // ./in.cue:10:5 // ./in.cue:11:5 } c: (string){ string } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/020_complex_interaction_of_groundness.txtar000066400000000000000000000026331474664451600313510ustar00rootroot00000000000000#name: complex interaction of groundness #evalFull -- in.cue -- res: [for x in a for y in x {y & {d: "b"}}] res: [ a.b.c & {d: "b"}] a: b: [C=string]: {d: string, s: "a" + d} a: b: c: d: string -- out/def -- res: [{ d: "b" s: "ab" } & (a.b.c & { d: "b" })] a: { b: { {[C=string]: { d: string, s: "a" + d }} c: { d: string s: "a" + d } } } -- out/legacy-debug -- <0>{res: [<1>{d: "b", s: "ab"}], a: <2>{b: <3>{[]: <4>(C: string)-><5>{d: string, s: ("a" + <5>.d)}, c: <6>{d: string, s: ("a" + <7>.d)}}}} -- out/compile -- --- in.cue { res: [ for _, x in 〈1;a〉 for _, y in 〈0;x〉 { (〈1;y〉 & { d: "b" }) }, ] res: [ (〈1;a〉.b.c & { d: "b" }), ] a: { b: { [string]: { d: string s: ("a" + 〈0;d〉) } } } a: { b: { c: { d: string } } } } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 3 Allocs: 7 Retain: 5 Unifications: 10 Conjuncts: 33 Disjuncts: 15 -- out/eval -- (struct){ res: (#list){ 0: (struct){ d: (string){ "b" } s: (string){ "ab" } } } a: (struct){ b: (struct){ c: (struct){ d: (string){ string } s: (_|_){ // [incomplete] a.b.c.s: non-concrete value string in operand to +: // ./in.cue:4:34 // ./in.cue:4:23 // ./in.cue:5:13 } } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/021_complex_groundness_2.txtar000066400000000000000000000045571474664451600265170ustar00rootroot00000000000000#name: complex groundness 2 #evalFull -- in.cue -- r1: f1 & {y: "c"} f1: {y: string, res: a.b.c & {d: y}} a: b: c: {d: string, s: "a" + d} a: b: [C=string]: {d: string, s: "a" + d} a: b: c: d: string -- out/def -- r1: f1 & { y: "c" } f1: { y: string res: a.b.c & { d: y } } a: { b: { {[C=string]: { d: string, s: "a" + d }} c: { d: string s: "a"+d & "a"+d } } } -- out/legacy-debug -- <0>{r1: <1>{y: "c", res: <2>{d: "c", s: "ac"}}, f1: <3>{y: string, res: <4>{d: string, s: (("a" + <5>.d) & ("a" + <5>.d))}}, a: <6>{b: <7>{[]: <8>(C: string)-><9>{d: string, s: ("a" + <9>.d)}, c: <10>{d: string, s: (("a" + <11>.d) & ("a" + <11>.d))}}}} -- out/compile -- --- in.cue { r1: (〈0;f1〉 & { y: "c" }) f1: { y: string res: (〈1;a〉.b.c & { d: 〈1;y〉 }) } a: { b: { c: { d: string s: ("a" + 〈0;d〉) } } } a: { b: { [string]: { d: string s: ("a" + 〈0;d〉) } } } a: { b: { c: { d: string } } } } -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 8 Allocs: 8 Retain: 6 Unifications: 16 Conjuncts: 63 Disjuncts: 22 -- out/eval -- (struct){ r1: (struct){ y: (string){ "c" } res: (struct){ d: (string){ "c" } s: (string){ "ac" } } } f1: (struct){ y: (string){ string } res: (struct){ d: (string){ string } s: (_|_){ // [incomplete] f1.res.s: non-concrete value string in operand to +: // ./in.cue:5:25 // ./in.cue:3:34 // ./in.cue:5:14 // ./in.cue:6:23 // ./in.cue:7:13 // f1.res.s: non-concrete value string in operand to +: // ./in.cue:6:34 // ./in.cue:3:34 // ./in.cue:5:14 // ./in.cue:6:23 // ./in.cue:7:13 } } } a: (struct){ b: (struct){ c: (struct){ d: (string){ string } s: (_|_){ // [incomplete] a.b.c.s: non-concrete value string in operand to +: // ./in.cue:5:25 // ./in.cue:5:14 // ./in.cue:6:23 // ./in.cue:7:13 // a.b.c.s: non-concrete value string in operand to +: // ./in.cue:6:34 // ./in.cue:5:14 // ./in.cue:6:23 // ./in.cue:7:13 } } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/022_references_from_template_to_concrete.txtar000066400000000000000000000044311474664451600317730ustar00rootroot00000000000000#name: references from template to concrete #evalFull -- in.cue -- res: [t] t: [X=string]: { a: c + b.str b: str: string c: "X" } t: x: {b: str: "DDDD"} -- out/def -- res: [t] t: { {[X=string]: { a: c + b.str, c: "X", b: { str: string } }} x: { a: "XDDDD" c: "X" b: { str: "DDDD" } } } -- out/export -- res: [{ x: { a: "XDDDD" c: "X" b: { str: "DDDD" } } }] t: { x: { a: "XDDDD" c: "X" b: { str: "DDDD" } } } -- out/yaml -- res: - x: a: XDDDD c: X b: str: DDDD t: x: a: XDDDD c: X b: str: DDDD -- out/json -- {"res":[{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}],"t":{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}} -- out/legacy-debug -- <0>{res: [<1>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <5>{a: "XDDDD", c: "X", b: <6>{str: "DDDD"}}}], t: <7>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <8>{a: "XDDDD", c: "X", b: <9>{str: "DDDD"}}}} -- out/compile -- --- in.cue { res: [ 〈1;t〉, ] t: { [string]: { a: (〈0;c〉 + 〈0;b〉.str) b: { str: string } c: "X" } } t: { x: { b: { str: "DDDD" } } } } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 7 Allocs: 7 Retain: 3 Unifications: 14 Conjuncts: 21 Disjuncts: 15 -- out/evalalpha -- (struct){ res: (#list){ 0: ~(t) } t: (struct){ x: (struct){ b: (struct){ str: (string){ "DDDD" } } a: (string){ "XDDDD" } c: (string){ "X" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,14 +1,6 @@ (struct){ res: (#list){ - 0: (struct){ - x: (struct){ - b: (struct){ - str: (string){ "DDDD" } - } - a: (string){ "XDDDD" } - c: (string){ "X" } - } - } + 0: ~(t) } t: (struct){ x: (struct){ -- out/eval -- (struct){ res: (#list){ 0: (struct){ x: (struct){ b: (struct){ str: (string){ "DDDD" } } a: (string){ "XDDDD" } c: (string){ "X" } } } } t: (struct){ x: (struct){ b: (struct){ str: (string){ "DDDD" } } a: (string){ "XDDDD" } c: (string){ "X" } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/024_Issue_#23.txtar000066400000000000000000000055741474664451600240220ustar00rootroot00000000000000#name: Issue #23 #evalFull -- in.cue -- x: {a: 1} | {a: 2} y: x & {a: 3} -- out/def -- x: { a: 1 } | { a: 2 } y: _|_ // ; empty disjunction: conflicting values 2 and 3 -- out/legacy-debug -- <0>{x: (<1>{a: 1} | <2>{a: 2}), y: _|_((1 & 3):empty disjunction: conflicting values 1 and 3;(2 & 3):empty disjunction: conflicting values 2 and 3)} -- out/compile -- --- in.cue { x: ({ a: 1 }|{ a: 2 }) y: (〈0;x〉 & { a: 3 }) } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 6 Allocs: 5 Retain: 0 Unifications: 7 Conjuncts: 15 Disjuncts: 11 -- out/evalalpha -- Errors: y: 2 errors in empty disjunction: y.a: conflicting values 1 and 3: ./in.cue:1:12 ./in.cue:2:12 y.a: conflicting values 2 and 3: ./in.cue:1:21 ./in.cue:2:12 Result: (_|_){ // [eval] x: (struct){ |((struct){ a: (int){ 1 } }, (struct){ a: (int){ 2 } }) } y: (_|_){ // [eval] y: 2 errors in empty disjunction: // y.a: conflicting values 1 and 3: // ./in.cue:1:12 // ./in.cue:2:12 // y.a: conflicting values 2 and 3: // ./in.cue:1:21 // ./in.cue:2:12 a: (int){ 3 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,11 +2,9 @@ y: 2 errors in empty disjunction: y.a: conflicting values 1 and 3: ./in.cue:1:12 - ./in.cue:2:4 ./in.cue:2:12 y.a: conflicting values 2 and 3: ./in.cue:1:21 - ./in.cue:2:4 ./in.cue:2:12 Result: @@ -21,17 +19,10 @@ // [eval] y: 2 errors in empty disjunction: // y.a: conflicting values 1 and 3: // ./in.cue:1:12 - // ./in.cue:2:4 // ./in.cue:2:12 // y.a: conflicting values 2 and 3: // ./in.cue:1:21 - // ./in.cue:2:4 - // ./in.cue:2:12 - a: (_|_){ - // [eval] y.a: conflicting values 2 and 3: - // ./in.cue:1:21 - // ./in.cue:2:4 - // ./in.cue:2:12 - } + // ./in.cue:2:12 + a: (int){ 3 } } } -- diff/todo/p3 -- Missing error positions. -- diff/explanation -- It is okay to show field a as long as the error is clear and points to the violating disjunction. -- out/eval -- Errors: y: 2 errors in empty disjunction: y.a: conflicting values 1 and 3: ./in.cue:1:12 ./in.cue:2:4 ./in.cue:2:12 y.a: conflicting values 2 and 3: ./in.cue:1:21 ./in.cue:2:4 ./in.cue:2:12 Result: (_|_){ // [eval] x: (struct){ |((struct){ a: (int){ 1 } }, (struct){ a: (int){ 2 } }) } y: (_|_){ // [eval] y: 2 errors in empty disjunction: // y.a: conflicting values 1 and 3: // ./in.cue:1:12 // ./in.cue:2:4 // ./in.cue:2:12 // y.a: conflicting values 2 and 3: // ./in.cue:1:21 // ./in.cue:2:4 // ./in.cue:2:12 a: (_|_){ // [eval] y.a: conflicting values 2 and 3: // ./in.cue:1:21 // ./in.cue:2:4 // ./in.cue:2:12 } } } 026_dont_convert_incomplete_errors_to_non-incomplete.txtar000066400000000000000000000063741474664451600343350ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/fulleval#name: dont convert incomplete errors to non-incomplete #evalFull -- in.cue -- import "strings" n1: {min: min} n2: -num n3: +num n4: num + num n5: num - num n6: num * num n7: num / num b1: !is s1: "\(str)" s2: strings.ContainsAny("dd") s3: strings.ContainsAny(str, "dd") str: string num: <4 is: bool -- out/def -- import "strings" n1: { min: min } n2: -num num: <4 n3: +num n4: num + num n5: num - num n6: num * num n7: num / num b1: !is is: bool s1: "\(str)" str: string s2: strings.ContainsAny("dd") s3: strings.ContainsAny(str, "dd") -- out/legacy-debug -- <0>{n1: <1>{min: <<2>.max, max: ><2>.min}, n2: -<3>.num, num: <4, n3: +<3>.num, n4: (<3>.num + <3>.num), n5: (<3>.num - <3>.num), n6: (<3>.num * <3>.num), n7: (<3>.num / <3>.num), b1: !<3>.is, is: bool, s1: ""+<3>.str+"", str: string, s2: strings.ContainsAny ("dd"), s3: <4>.ContainsAny (<3>.str,"dd")} -- out/evalalpha/stats -- Leaks: 17 Freed: 0 Reused: 0 Allocs: 17 Retain: 0 Unifications: 17 Conjuncts: 35 Disjuncts: 0 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- diff old new --- old +++ new @@ -1,9 +1,9 @@ -Leaks: 0 -Freed: 17 -Reused: 12 -Allocs: 5 -Retain: 75 +Leaks: 17 +Freed: 0 +Reused: 0 +Allocs: 17 +Retain: 0 Unifications: 17 -Conjuncts: 71 -Disjuncts: 82 +Conjuncts: 35 +Disjuncts: 0 -- out/eval/stats -- Leaks: 0 Freed: 17 Reused: 12 Allocs: 5 Retain: 75 Unifications: 17 Conjuncts: 71 Disjuncts: 82 -- out/eval -- (struct){ n1: (struct){ min: (_|_){ // [cycle] cycle error } max: (_|_){ // [cycle] cycle error } } n2: (_|_){ // [incomplete] n2: operand num of '-' not concrete (was number): // ./in.cue:4:6 } n3: (_|_){ // [incomplete] n3: operand num of '+' not concrete (was number): // ./in.cue:5:6 } n4: (_|_){ // [incomplete] n4: non-concrete value <4 in operand to +: // ./in.cue:6:5 // ./in.cue:18:6 } n5: (_|_){ // [incomplete] n5: non-concrete value <4 in operand to -: // ./in.cue:7:5 // ./in.cue:18:6 } n6: (_|_){ // [incomplete] n6: non-concrete value <4 in operand to *: // ./in.cue:8:5 // ./in.cue:18:6 } n7: (_|_){ // [incomplete] n7: non-concrete value <4 in operand to /: // ./in.cue:9:5 // ./in.cue:18:6 } b1: (_|_){ // [incomplete] b1: operand is of '!' not concrete (was bool): // ./in.cue:11:6 } s1: (_|_){ // [incomplete] s1: invalid interpolation: non-concrete value string (type string): // ./in.cue:13:5 // ./in.cue:17:6 } s2: (string){ strings.ContainsAny("dd") } s3: (_|_){ // [incomplete] s3: error in call to strings.ContainsAny: non-concrete value string: // ./in.cue:15:5 // ./in.cue:17:6 } str: (string){ string } num: (number){ <4 } is: (bool){ bool } } -- out/compile -- --- in.cue { n1: { min: <〈0;max〉 max: >〈0;min〉 } n2: -〈0;num〉 n3: +〈0;num〉 n4: (〈0;num〉 + 〈0;num〉) n5: (〈0;num〉 - 〈0;num〉) n6: (〈0;num〉 * 〈0;num〉) n7: (〈0;num〉 / 〈0;num〉) b1: !〈0;is〉 s1: "\(〈0;str〉)" s2: 〈import;strings〉.ContainsAny("dd") s3: 〈import;strings〉.ContainsAny(〈0;str〉, "dd") str: string num: <4 is: bool } cue-lang-cue-db9cc73/cue/testdata/fulleval/027_len_of_incomplete_types.txtar000066400000000000000000000031231474664451600272570ustar00rootroot00000000000000#name: len of incomplete types #evalFull -- in.cue -- args: *[] | [...string] v1: len(args) v2: len([]) v3: len({}) v4: len({a: 3}) v5: len({a: 3} | {a: 4}) v6: len('sf' | 'dd') v7: len([2] | *[1, 2]) v8: len([2] | [1, 2]) v9: len("😂") v10: len("") -- out/def -- args: *[] | [...string] v1: 0 v2: 0 v3: 0 v4: 1 v5: len({ a: 3 } | { a: 4 }) v6: len('sf' | 'dd') v7: 2 v8: len([2] | [1, 2]) v9: 4 v10: 0 -- out/legacy-debug -- <0>{args: [], v1: 0, v2: 0, v3: 0, v4: 1, v5: len ((<1>{a: 3} | <2>{a: 4})), v6: len (('sf' | 'dd')), v7: 2, v8: len (([2] | [1,2])), v9: 4, v10: 0} -- out/eval/stats -- Leaks: 3 Freed: 90 Reused: 84 Allocs: 9 Retain: 3 Unifications: 59 Conjuncts: 105 Disjuncts: 93 -- out/eval -- (struct){ args: (list){ |(*(#list){ }, (list){ }) } v1: (int){ 0 } v2: (int){ 0 } v3: (int){ 0 } v4: (int){ 1 } v5: (_|_){ // [incomplete] v5: unresolved disjunction {a:3} | {a:4} (type struct): // ./in.cue:6:7 } v6: (_|_){ // [incomplete] v6: unresolved disjunction 'sf' | 'dd' (type bytes): // ./in.cue:7:7 } v7: (int){ 2 } v8: (_|_){ // [incomplete] v8: unresolved disjunction [2] | [1,2] (type list): // ./in.cue:9:7 } v9: (int){ 4 } v10: (int){ 0 } } -- out/compile -- --- in.cue { args: (*[]|[ ...string, ]) v1: len(〈0;args〉) v2: len([]) v3: len({}) v4: len({ a: 3 }) v5: len(({ a: 3 }|{ a: 4 })) v6: len(('sf'|'dd')) v7: len(([ 2, ]|*[ 1, 2, ])) v8: len(([ 2, ]|[ 1, 2, ])) v9: len("😂") v10: len("") } cue-lang-cue-db9cc73/cue/testdata/fulleval/028_slice_rewrite_bug.txtar000066400000000000000000000017161474664451600260560ustar00rootroot00000000000000#name: slice rewrite bug #evalFull -- in.cue -- fn: { arg: [...int] & [1] out: arg[1:] } fn1: fn & {arg: [1]} -- out/def -- fn: { arg: [1] out: [] } fn1: fn & { arg: [1] } -- out/export -- fn: { arg: [1] out: [] } fn1: { arg: [1] out: [] } -- out/yaml -- fn: arg: - 1 out: [] fn1: arg: - 1 out: [] -- out/json -- {"fn":{"arg":[1],"out":[]},"fn1":{"arg":[1],"out":[]}} -- out/legacy-debug -- <0>{fn: <1>{arg: [1], out: []}, fn1: <2>{arg: [1], out: []}} -- out/compile -- --- in.cue { fn: { arg: ([ ...int, ] & [ 1, ]) out: 〈0;arg〉[1:] } fn1: (〈0;fn〉 & { arg: [ 1, ] }) } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 5 Allocs: 4 Retain: 0 Unifications: 9 Conjuncts: 17 Disjuncts: 9 -- out/eval -- (struct){ fn: (struct){ arg: (#list){ 0: (int){ 1 } } out: (#list){ } } fn1: (struct){ arg: (#list){ 0: (int){ 1 } } out: (#list){ } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/029_Issue_#94.txtar000066400000000000000000000047041474664451600240310ustar00rootroot00000000000000#name: Issue #94 #evalFull -- in.cue -- foo: { opt?: 1 "txt": 2 #def: 3 regular: 4 _hidden: 5 } comp: {for k, v in foo {"\(k)": v}} select: { opt: foo.opt "txt": foo.txt #def: foo.#def regular: foo.regular _hidden: foo._hidden } index: { opt: foo["opt"] "txt": foo["txt"] #def: foo["#def"] regular: foo["regular"] _hidden: foo["_hidden"] } -- out/def -- foo: { opt?: 1 txt: 2 #def: 3 regular: 4 _hidden: 5 } comp: { txt: 2 regular: 4 } select: { opt: foo.opt txt: 2 #def: 3 regular: 4 _hidden: 5 } index: { opt: foo["opt"] txt: 2 #def: foo["#def"] regular: 4 _hidden: foo["_hidden"] } -- out/legacy-debug -- <0>{foo: <1>{opt?: 1, txt: 2, #def: 3, regular: 4, _hidden: 5}, comp: <2>{txt: 2, regular: 4}, select: <3>{opt: <4>.foo.opt, txt: 2, #def: 3, regular: 4, _hidden: 5}, index: <5>{opt: <4>.foo["opt"], txt: 2, #def: <4>.foo["#def"], regular: 4, _hidden: <4>.foo["_hidden"]}} -- out/compile -- --- in.cue { foo: { opt?: 1 txt: 2 #def: 3 regular: 4 _hidden: 5 } comp: { for k, v in 〈1;foo〉 { "\(〈1;k〉)": 〈1;v〉 } } select: { opt: 〈1;foo〉.opt txt: 〈1;foo〉.txt #def: 〈1;foo〉.#def regular: 〈1;foo〉.regular _hidden: 〈1;foo〉._hidden } index: { opt: 〈1;foo〉["opt"] txt: 〈1;foo〉["txt"] #def: 〈1;foo〉["#def"] regular: 〈1;foo〉["regular"] _hidden: 〈1;foo〉["_hidden"] } } -- out/eval/stats -- Leaks: 0 Freed: 22 Reused: 19 Allocs: 3 Retain: 0 Unifications: 22 Conjuncts: 32 Disjuncts: 22 -- out/eval -- (struct){ foo: (struct){ opt?: (int){ 1 } txt: (int){ 2 } #def: (int){ 3 } regular: (int){ 4 } _hidden: (int){ 5 } } comp: (struct){ txt: (int){ 2 } regular: (int){ 4 } } select: (struct){ opt: (_|_){ // [incomplete] select.opt: cannot reference optional field: opt: // ./in.cue:10:15 } txt: (int){ 2 } #def: (int){ 3 } regular: (int){ 4 } _hidden: (int){ 5 } } index: (struct){ opt: (_|_){ // [incomplete] index.opt: cannot reference optional field: opt: // ./in.cue:17:15 } txt: (int){ 2 } #def: (_|_){ // [incomplete] index.#def: undefined field: "#def": // ./in.cue:19:15 } regular: (int){ 4 } _hidden: (_|_){ // [incomplete] index._hidden: undefined field: "_hidden": // ./in.cue:21:15 } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/030_retain_references_with_interleaved_embedding.txtar000066400000000000000000000022611474664451600334440ustar00rootroot00000000000000#name: retain references with interleaved embedding #evalFull -- in.cue -- a: d: { #base #info: {...} Y: #info.X } #base: { #info: {...} } a: [Name=string]: {#info: { X: "foo" }} -- out/def -- a: { {[Name=string]: { #info: { X: "foo" } }} d: { #info: { ... } Y: #info.X #base } } #base: { #info: { ... } } -- out/export -- a: { d: { Y: "foo" } } -- out/yaml -- a: d: Y: foo -- out/json -- {"a":{"d":{"Y":"foo"}}} -- out/legacy-debug -- <0>{a: <1>{[]: <2>(Name: string)-><3>{#info: <4>C{X: "foo"}}, d: <5>C{#info: <6>C{X: "foo"}, Y: "foo"}}, #base: <7>C{#info: <8>{...}}} -- out/compile -- --- in.cue { a: { d: { 〈2;#base〉 #info: { ... } Y: 〈0;#info〉.X } } #base: { #info: { ... } } a: { [string]: { #info: { X: "foo" } } } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 3 Allocs: 5 Retain: 1 Unifications: 8 Conjuncts: 19 Disjuncts: 9 -- out/eval -- (struct){ a: (struct){ d: (#struct){ #info: (#struct){ X: (string){ "foo" } } Y: (string){ "foo" } } } #base: (#struct){ #info: (#struct){ } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/031_comparison_against_bottom.txtar000066400000000000000000000043531474664451600276170ustar00rootroot00000000000000#name: comparison against bottom #evalFull -- in.cue -- a: _|_ == _|_ b: err == 1 & 2 // not a literal error, so not allowed c: err == _|_ // allowed d: err != _|_ // allowed e: err != 1 & 3 // z: err == err // TODO: should infer to be true? f: ({a: 1} & {a: 2}) == _|_ g: ({a: 1} & {b: 2}) == _|_ h: _|_ == ({a: 1} & {a: 2}) i: _|_ == ({a: 1} & {b: 2}) err: 1 & 2 -- out/def -- a: true b: _|_ // conflicting values 1 and 2 err: _|_ // conflicting values 1 and 2 c: true d: false e: _|_ // conflicting values 1 and 2 // z: err == err // TODO: should infer to be true? f: true g: false h: true i: false -- out/legacy-debug -- <0>{a: true, b: _|_((1 & 2):conflicting values 1 and 2), err: _|_((1 & 2):conflicting values 1 and 2), c: true, d: false, e: _|_((1 & 2):conflicting values 1 and 2), f: true, g: false, h: true, i: false} -- out/compile -- --- in.cue { a: (_|_(explicit error (_|_ literal) in source) == _|_(explicit error (_|_ literal) in source)) b: ((〈0;err〉 == 1) & 2) c: (〈0;err〉 == _|_(explicit error (_|_ literal) in source)) d: (〈0;err〉 != _|_(explicit error (_|_ literal) in source)) e: ((〈0;err〉 != 1) & 3) f: (({ a: 1 } & { a: 2 }) == _|_(explicit error (_|_ literal) in source)) g: (({ a: 1 } & { b: 2 }) == _|_(explicit error (_|_ literal) in source)) h: (_|_(explicit error (_|_ literal) in source) == ({ a: 1 } & { a: 2 })) i: (_|_(explicit error (_|_ literal) in source) == ({ a: 1 } & { b: 2 })) err: (1 & 2) } -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 16 Allocs: 5 Retain: 4 Unifications: 21 Conjuncts: 28 Disjuncts: 21 -- out/eval -- Errors: err: conflicting values 2 and 1: ./in.cue:12:6 ./in.cue:12:10 Result: (_|_){ // [eval] a: (bool){ true } b: (_|_){ // [eval] err: conflicting values 2 and 1: // ./in.cue:12:6 // ./in.cue:12:10 } c: (bool){ true } d: (bool){ false } e: (_|_){ // [eval] err: conflicting values 2 and 1: // ./in.cue:12:6 // ./in.cue:12:10 } f: (bool){ true } g: (bool){ false } h: (bool){ true } i: (bool){ false } err: (_|_){ // [eval] err: conflicting values 2 and 1: // ./in.cue:12:6 // ./in.cue:12:10 } } 032_or_builtin_should_not_fail_on_non-concrete_empty_list.txtar000066400000000000000000000025271474664451600353140ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/fulleval#name: or builtin should not fail on non-concrete empty list #evalFull -- in.cue -- #Workflow: { jobs: { [jobID=string]: { } } #JobID: or([for k, _ in jobs {k}]) } foo: #Workflow & { jobs: foo: { } } -- out/def -- #Workflow: { jobs: { [jobID=string]: {} } #JobID: or([for k, _ in jobs { k }]) } foo: #Workflow & { jobs: { foo: {} } } -- out/export -- foo: { jobs: { foo: {} } } -- out/yaml -- foo: jobs: foo: {} -- out/json -- {"foo":{"jobs":{"foo":{}}}} -- out/legacy-debug -- <0>{#Workflow: <1>C{jobs: <2>{[]: <3>(jobID: string)-><4>C{}, }, #JobID: or ([ <5>for k, _ in <6>.jobs yield <5>.k ])}, foo: <7>C{jobs: <8>{[]: <9>(jobID: string)-><10>C{}, foo: <11>C{}}, #JobID: "foo"}} -- out/eval/stats -- Leaks: 6 Freed: 11 Reused: 6 Allocs: 11 Retain: 6 Unifications: 15 Conjuncts: 32 Disjuncts: 17 -- out/eval -- (struct){ #Workflow: (#struct){ jobs: (#struct){ } #JobID: (_|_){ // [incomplete] empty list in call to or: // ./in.cue:6:10 } } foo: (#struct){ jobs: (#struct){ foo: (#struct){ } } #JobID: (string){ "foo" } } } -- out/compile -- --- in.cue { #Workflow: { jobs: { [string]: {} } #JobID: or([ for k, _ in 〈1;jobs〉 { 〈1;k〉 }, ]) } foo: (〈0;#Workflow〉 & { jobs: { foo: {} } }) } cue-lang-cue-db9cc73/cue/testdata/fulleval/034_label_and_field_aliases.txtar000066400000000000000000000023101474664451600271120ustar00rootroot00000000000000#name: label and field aliases #evalFull -- in.cue -- p: [ID=string]: {name: ID} A="foo=bar": "str" a: A B=bb: 4 b1: B b1: bb C="\(a)": 5 c: C -- out/def -- p: { [ID=string]: { name: ID } } "foo=bar": "str" a: "str" bb: 4 b1: 4 c: 5 str: 5 -- out/export -- p: {} "foo=bar": "str" a: "str" bb: 4 b1: 4 c: 5 str: 5 -- out/yaml -- p: {} foo=bar: str a: str bb: 4 b1: 4 c: 5 str: 5 -- out/json -- {"p":{},"foo=bar":"str","a":"str","bb":4,"b1":4,"c":5,"str":5} -- out/legacy-debug -- <0>{p: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, }, "foo=bar": "str", a: "str", bb: 4, b1: 4, c: 5, str: 5} -- out/compile -- --- in.cue { p: { [string]: { name: 〈1;-〉 } } "foo=bar": "str" a: 〈0;"foo=bar"〉 bb: 4 b1: 〈0;bb〉 b1: 〈0;bb〉 "\(〈0;a〉)": 5 c: 〈0;("\(〈0;a〉)")〉 } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 4 Allocs: 4 Retain: 3 Unifications: 8 Conjuncts: 10 Disjuncts: 9 -- out/eval -- (struct){ p: (struct){ } "foo=bar": (string){ "str" } a: (string){ "str" } bb: (int){ 4 } b1: (int){ 4 } c: (int){ 5 } str: (int){ 5 } } cue-lang-cue-db9cc73/cue/testdata/fulleval/035_optionals_with_label_filters.txtar000066400000000000000000000136061474664451600303120ustar00rootroot00000000000000#name: optionals with label filters #evalFull -- in.cue -- #JobID: =~"^[a-zA-Z]*$" #Job: { name: string cmd: string } #Jobs: { {[#JobID]: #Job} {[=~"Test$"]: name: =~"^test"}// Must work without ... } jobs: foo: name: "allGood" jobs: foo: name: "allGood" jobs1: #Jobs jobs1: foo1: {} // faulty jobs2: #Jobs jobs2: fooTest: name: "badName" // faulty jobs3: #Jobs jobs3: [string]: #Job jobs3: fooTest1: name: "badName" // faulty -- out/def -- #JobID: =~"^[a-zA-Z]*$" #Job: { name: string cmd: string } #Jobs: { {[#JobID]: #Job} {[=~"Test$"]: { name: =~"^test", ... }} } jobs: { foo: { name: "allGood" } } jobs1: _|_ // field "foo1" not allowed in closed struct jobs2: #Jobs & { fooTest: { name: "badName" } } jobs3: _|_ // field "fooTest1" not allowed in closed struct -- out/legacy-debug -- <0>{#JobID: =~"^[a-zA-Z]*$", #Job: <1>C{name: string, cmd: string}, #Jobs: <2>C{[=~"^[a-zA-Z]*$"]: <3>(_: string)-><4>.#Job, [=~"Test$"]: <5>(_: string)-><6>C{name: =~"^test"}, }, jobs: <7>{foo: <8>{name: "allGood"}}, jobs1: _|_(<9>{}:field "foo1" not allowed in closed struct), jobs2: <10>C{[=~"^[a-zA-Z]*$"]: <11>(_: string)-><4>.#Job, [=~"Test$"]: <12>(_: string)-><13>C{name: =~"^test"}, fooTest: _|_(string:field "cmd" not allowed in closed struct)}, jobs3: _|_(<14>{name: "badName"}:field "fooTest1" not allowed in closed struct)} -- out/compile -- --- in.cue { #JobID: =~"^[a-zA-Z]*$" #Job: { name: string cmd: string } #Jobs: { { [〈2;#JobID〉]: 〈2;#Job〉 } { [=~"Test$"]: { name: =~"^test" } } } jobs: { foo: { name: "allGood" } } jobs: { foo: { name: "allGood" } } jobs1: 〈0;#Jobs〉 jobs1: { foo1: {} } jobs2: 〈0;#Jobs〉 jobs2: { fooTest: { name: "badName" } } jobs3: 〈0;#Jobs〉 jobs3: { [string]: 〈1;#Job〉 } jobs3: { fooTest1: { name: "badName" } } } -- out/eval/stats -- Leaks: 0 Freed: 19 Reused: 15 Allocs: 4 Retain: 0 Unifications: 19 Conjuncts: 45 Disjuncts: 19 -- out/evalalpha -- Errors: jobs1.foo1: field not allowed: ./in.cue:9:16 ./in.cue:16:8 jobs3.fooTest1: field not allowed: ./in.cue:9:16 ./in.cue:22:8 ./in.cue:23:8 jobs2.fooTest.name: invalid value "badName" (out of bound =~"^test"): ./in.cue:9:22 ./in.cue:3:8 ./in.cue:19:23 Result: (_|_){ // [eval] #JobID: (string){ =~"^[a-zA-Z]*$" } #Job: (#struct){ name: (string){ string } cmd: (string){ string } } #Jobs: (#struct){ } jobs: (struct){ foo: (struct){ name: (string){ "allGood" } } } jobs1: (_|_){ // [eval] foo1: (_|_){ // [eval] jobs1.foo1: field not allowed: // ./in.cue:9:16 // ./in.cue:16:8 } } jobs2: (_|_){ // [eval] fooTest: (_|_){ // [eval] name: (_|_){ // [eval] jobs2.fooTest.name: invalid value "badName" (out of bound =~"^test"): // ./in.cue:9:22 // ./in.cue:3:8 // ./in.cue:19:23 } cmd: (string){ string } } } jobs3: (_|_){ // [eval] fooTest1: (_|_){ // [eval] jobs3.fooTest1: field not allowed: // ./in.cue:9:16 // ./in.cue:22:8 // ./in.cue:23:8 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,15 +1,9 @@ Errors: jobs1.foo1: field not allowed: - ./in.cue:6:8 - ./in.cue:7:2 - ./in.cue:9:2 - ./in.cue:15:17 + ./in.cue:9:16 ./in.cue:16:8 jobs3.fooTest1: field not allowed: - ./in.cue:6:8 - ./in.cue:7:2 - ./in.cue:9:2 - ./in.cue:21:8 + ./in.cue:9:16 ./in.cue:22:8 ./in.cue:23:8 jobs2.fooTest.name: invalid value "badName" (out of bound =~"^test"): @@ -36,10 +30,7 @@ // [eval] foo1: (_|_){ // [eval] jobs1.foo1: field not allowed: - // ./in.cue:6:8 - // ./in.cue:7:2 - // ./in.cue:9:2 - // ./in.cue:15:17 + // ./in.cue:9:16 // ./in.cue:16:8 } } @@ -60,14 +51,9 @@ // [eval] fooTest1: (_|_){ // [eval] jobs3.fooTest1: field not allowed: - // ./in.cue:6:8 - // ./in.cue:7:2 - // ./in.cue:9:2 - // ./in.cue:21:8 + // ./in.cue:9:16 // ./in.cue:22:8 // ./in.cue:23:8 - name: (string){ "badName" } - cmd: (string){ string } } } } -- diff/todo/p2 -- Missing error positions. -- out/eval -- Errors: jobs1.foo1: field not allowed: ./in.cue:6:8 ./in.cue:7:2 ./in.cue:9:2 ./in.cue:15:17 ./in.cue:16:8 jobs3.fooTest1: field not allowed: ./in.cue:6:8 ./in.cue:7:2 ./in.cue:9:2 ./in.cue:21:8 ./in.cue:22:8 ./in.cue:23:8 jobs2.fooTest.name: invalid value "badName" (out of bound =~"^test"): ./in.cue:9:22 ./in.cue:3:8 ./in.cue:19:23 Result: (_|_){ // [eval] #JobID: (string){ =~"^[a-zA-Z]*$" } #Job: (#struct){ name: (string){ string } cmd: (string){ string } } #Jobs: (#struct){ } jobs: (struct){ foo: (struct){ name: (string){ "allGood" } } } jobs1: (_|_){ // [eval] foo1: (_|_){ // [eval] jobs1.foo1: field not allowed: // ./in.cue:6:8 // ./in.cue:7:2 // ./in.cue:9:2 // ./in.cue:15:17 // ./in.cue:16:8 } } jobs2: (_|_){ // [eval] fooTest: (_|_){ // [eval] name: (_|_){ // [eval] jobs2.fooTest.name: invalid value "badName" (out of bound =~"^test"): // ./in.cue:9:22 // ./in.cue:3:8 // ./in.cue:19:23 } cmd: (string){ string } } } jobs3: (_|_){ // [eval] fooTest1: (_|_){ // [eval] jobs3.fooTest1: field not allowed: // ./in.cue:6:8 // ./in.cue:7:2 // ./in.cue:9:2 // ./in.cue:21:8 // ./in.cue:22:8 // ./in.cue:23:8 name: (string){ "badName" } cmd: (string){ string } } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/040.txtar000066400000000000000000000040511474664451600222660ustar00rootroot00000000000000#evalFull -- in.cue -- #Task: { { op: "pull" tag: *"latest" | string refToTag: tag tagExpr: tag + "dd" tagInString: "\(tag)" } | { op: "scratch" } } foo: #Task & {"op": "pull"} -- out/def -- #Task: { op: "pull" tag: *"latest" | string refToTag: tag tagExpr: "latestdd" tagInString: "latest" } | { op: "scratch" } foo: #Task & { op: "pull" } -- out/export -- foo: { op: "pull" tag: "latest" refToTag: "latest" tagExpr: "latestdd" tagInString: "latest" } -- out/yaml -- foo: op: pull tag: latest refToTag: latest tagExpr: latestdd tagInString: latest -- out/json -- {"foo":{"op":"pull","tag":"latest","refToTag":"latest","tagExpr":"latestdd","tagInString":"latest"}} -- out/legacy-debug -- <0>{#Task: (<1>C{op: "pull", tag: (*"latest" | string), refToTag: <1>.tag, tagExpr: (<1>.tag + "dd"), tagInString: ""+<1>.tag+""} | <2>C{op: "scratch"}), foo: <3>C{op: "pull", tag: "latest", refToTag: "latest", tagExpr: "latestdd", tagInString: "latest"}} -- out/compile -- --- in.cue { #Task: { ({ op: "pull" tag: (*"latest"|string) refToTag: 〈0;tag〉 tagExpr: (〈0;tag〉 + "dd") tagInString: "\(〈0;tag〉)" }|{ op: "scratch" }) } foo: (〈0;#Task〉 & { op: "pull" }) } -- out/eval/stats -- Leaks: 0 Freed: 27 Reused: 21 Allocs: 6 Retain: 0 Unifications: 15 Conjuncts: 35 Disjuncts: 27 -- out/eval -- (struct){ #Task: (#struct){ |((#struct){ op: (string){ "pull" } tag: (string){ |(*(string){ "latest" }, (string){ string }) } refToTag: (string){ |(*(string){ "latest" }, (string){ string }) } tagExpr: (string){ "latestdd" } tagInString: (string){ "latest" } }, (#struct){ op: (string){ "scratch" } }) } foo: (#struct){ op: (string){ "pull" } tag: (string){ |(*(string){ "latest" }, (string){ string }) } refToTag: (string){ |(*(string){ "latest" }, (string){ string }) } tagExpr: (string){ "latestdd" } tagInString: (string){ "latest" } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/041.txtar000066400000000000000000000012421474664451600222660ustar00rootroot00000000000000#evalFull -- in.cue -- t: { #ok: *true | bool if #ok { x: int } } s: t & { #ok: false } -- out/def -- t: { x: int #ok: *true | bool } s: t & { #ok: false } -- out/legacy-debug -- <0>{t: <1>{x: int, #ok: true}, s: <2>{#ok: false}} -- out/compile -- --- in.cue { t: { #ok: (*true|bool) if 〈0;#ok〉 { x: int } } s: (〈0;t〉 & { #ok: false }) } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 6 Allocs: 5 Retain: 0 Unifications: 7 Conjuncts: 13 Disjuncts: 11 -- out/eval -- (struct){ t: (struct){ #ok: (bool){ |(*(bool){ true }, (bool){ bool }) } x: (int){ int } } s: (struct){ #ok: (bool){ false } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/042_cross-dependent_comprehension.txtar000066400000000000000000000030021474664451600303710ustar00rootroot00000000000000#name: cross-dependent comprehension #evalFull -- in.cue -- #a: { if b { c: 4 } b: bool } x: (#a & {b: true}) & {c: 4} y: x -- out/def -- x: _|_ // field "c" not allowed in closed struct y: _|_ // field "c" not allowed in closed struct #a: { b: bool if b { c: 4 } } -- out/legacy-debug -- <0>{x: _|_(4:field "c" not allowed in closed struct), y: _|_(4:field "c" not allowed in closed struct), #a: <1>C{b: bool if <2>.b yield <3>C{c: 4}}} -- out/compile -- --- in.cue { #a: { if 〈0;b〉 { c: 4 } b: bool } x: ((〈0;#a〉 & { b: true }) & { c: 4 }) y: 〈0;x〉 } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 6 Allocs: 4 Retain: 4 Unifications: 10 Conjuncts: 18 Disjuncts: 12 -- out/evalalpha -- (struct){ #a: (_|_){ // [incomplete] #a: incomplete bool: bool: // ./in.cue:5:5 b: (bool){ bool } } x: (#struct){ b: (bool){ true } c: (int){ 4 } } y: ~(x) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -5,11 +5,8 @@ b: (bool){ bool } } x: (#struct){ - c: (int){ 4 } - b: (bool){ true } - } - y: (#struct){ - c: (int){ 4 } - b: (bool){ true } - } + b: (bool){ true } + c: (int){ 4 } + } + y: ~(x) } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ #a: (_|_){ // [incomplete] #a: incomplete bool: bool: // ./in.cue:5:5 b: (bool){ bool } } x: (#struct){ c: (int){ 4 } b: (bool){ true } } y: (#struct){ c: (int){ 4 } b: (bool){ true } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/043_optional_expanded_before_lookup.txtar000066400000000000000000000025021474664451600307600ustar00rootroot00000000000000#name: optional expanded before lookup #evalFull -- in.cue -- test: [ID=_]: { name: ID } test: A: { field1: "1" field2: "2" } B: test.A & {} -- out/def -- test: { {[ID=string]: { name: ID }} A: { name: "A" field1: "1" field2: "2" } } B: test.A & {} -- out/export -- test: { A: { name: "A" field1: "1" field2: "2" } } B: { name: "A" field1: "1" field2: "2" } -- out/yaml -- test: A: name: A field1: "1" field2: "2" B: name: A field1: "1" field2: "2" -- out/json -- {"test":{"A":{"name":"A","field1":"1","field2":"2"}},"B":{"name":"A","field1":"1","field2":"2"}} -- out/legacy-debug -- <0>{test: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, A: <4>{name: "A", field1: "1", field2: "2"}}, B: <5>{name: "A", field1: "1", field2: "2"}} -- out/compile -- --- in.cue { test: { [_]: { name: 〈1;-〉 } } test: { A: { field1: "1" field2: "2" } } B: (〈0;test〉.A & {}) } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 6 Allocs: 4 Retain: 0 Unifications: 10 Conjuncts: 15 Disjuncts: 10 -- out/eval -- (struct){ test: (struct){ A: (struct){ field1: (string){ "1" } field2: (string){ "2" } name: (string){ "A" } } } B: (struct){ field1: (string){ "1" } field2: (string){ "2" } name: (string){ "A" } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/044_Issue_#178.txtar000066400000000000000000000020621474664451600241040ustar00rootroot00000000000000#name: Issue #178 #evalFull -- in.cue -- import "encoding/csv" import "encoding/hex" foo: csv.Decode(data) data: bytes len: int bar: hex.EncodedLen(len) -- out/def -- import ( "encoding/csv" "encoding/hex" ) foo: csv.Decode(data) data: bytes len: int bar: hex.EncodedLen(len) -- out/legacy-debug -- <0>{foo: <1>.Decode (<2>.data), data: bytes, len: int, bar: <3>.EncodedLen (<2>.len)} -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 2 Allocs: 3 Retain: 5 Unifications: 5 Conjuncts: 13 Disjuncts: 10 -- out/eval -- (struct){ foo: (_|_){ // [incomplete] foo: error in call to encoding/csv.Decode: non-concrete value bytes: // ./in.cue:5:7 // ./in.cue:6:7 } data: (bytes){ bytes } len: (int){ int } bar: (_|_){ // [incomplete] bar: error in call to encoding/hex.EncodedLen: non-concrete value int: // ./in.cue:9:6 // ./in.cue:8:6 } } -- out/compile -- --- in.cue { foo: 〈import;"encoding/csv"〉.Decode(〈0;data〉) data: bytes len: int bar: 〈import;"encoding/hex"〉.EncodedLen(〈0;len〉) } cue-lang-cue-db9cc73/cue/testdata/fulleval/046_non-structural_direct_cycles.txtar000066400000000000000000000042661474664451600302600ustar00rootroot00000000000000#name: non-structural direct cycles #evalFull -- in.cue -- c1: {bar: baz: 2} & c1.bar c2: {bar: 1} & c2.bar -- out/def -- c1: { bar: { baz: 2 } } & c1.bar c2: _|_ // conflicting values {bar: 1} and 1 (mismatched types struct and int) -- out/legacy-debug -- <0>{c1: <1>{bar: <2>{baz: 2}, baz: 2}, c2: _|_(conflicting values {bar: 1} and 1 (mismatched types struct and int))} -- out/compile -- --- in.cue { c1: ({ bar: { baz: 2 } } & 〈0;c1〉.bar) c2: ({ bar: 1 } & 〈0;c2〉.bar) } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 3 Allocs: 4 Retain: 2 Unifications: 7 Conjuncts: 10 Disjuncts: 8 -- out/evalalpha -- Errors: c2: conflicting values 1 and {bar:1} (mismatched types int and struct): ./in.cue:2:5 ./in.cue:2:16 c2: cannot combine regular field "bar" with 1: ./in.cue:2:16 Result: (_|_){ // [eval] c1: (struct){ bar: (struct){ baz: (int){ 2 } } baz: (int){ 2 } } c2: (_|_){ // [eval] c2: conflicting values 1 and {bar:1} (mismatched types int and struct): // ./in.cue:2:5 // ./in.cue:2:16 // c2: cannot combine regular field "bar" with 1: // ./in.cue:2:16 bar: (int){ 1 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,6 +2,8 @@ c2: conflicting values 1 and {bar:1} (mismatched types int and struct): ./in.cue:2:5 ./in.cue:2:16 +c2: cannot combine regular field "bar" with 1: + ./in.cue:2:16 Result: (_|_){ @@ -16,6 +18,8 @@ // [eval] c2: conflicting values 1 and {bar:1} (mismatched types int and struct): // ./in.cue:2:5 // ./in.cue:2:16 + // c2: cannot combine regular field "bar" with 1: + // ./in.cue:2:16 bar: (int){ 1 } } } -- diff/todo/p3 -- Additional error message. Seems okay. -- out/eval -- Errors: c2: conflicting values 1 and {bar:1} (mismatched types int and struct): ./in.cue:2:5 ./in.cue:2:16 Result: (_|_){ // [eval] c1: (struct){ bar: (struct){ baz: (int){ 2 } } baz: (int){ 2 } } c2: (_|_){ // [eval] c2: conflicting values 1 and {bar:1} (mismatched types int and struct): // ./in.cue:2:5 // ./in.cue:2:16 bar: (int){ 1 } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/047_dont_bind_to_string_labels.txtar000066400000000000000000000011161474664451600277260ustar00rootroot00000000000000#name: dont bind to string labels #evalFull -- in.cue -- x: 1 y: { "x": 2 z: x } -- out/def -- x: 1 y: { x: 2 z: 1 } -- out/export -- x: 1 y: { x: 2 z: 1 } -- out/yaml -- x: 1 y: x: 2 z: 1 -- out/json -- {"x":1,"y":{"x":2,"z":1}} -- out/legacy-debug -- <0>{x: 1, y: <1>{x: 2, z: 1}} -- out/compile -- --- in.cue { x: 1 y: { x: 2 z: 〈1;x〉 } } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 2 Allocs: 3 Retain: 0 Unifications: 5 Conjuncts: 6 Disjuncts: 5 -- out/eval -- (struct){ x: (int){ 1 } y: (struct){ x: (int){ 2 } z: (int){ 1 } } } cue-lang-cue-db9cc73/cue/testdata/fulleval/048_dont_pass_incomplete_values_to_builtins.txtar000066400000000000000000000012251474664451600325610ustar00rootroot00000000000000#name: dont pass incomplete values to builtins #evalFull -- in.cue -- import "encoding/json" input: string foo: json.Marshal(input) -- out/def -- import "encoding/json" input: string foo: json.Marshal(input) -- out/legacy-debug -- <0>{input: string, foo: <1>.Marshal (<2>.input)} -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 1 Allocs: 2 Retain: 0 Unifications: 3 Conjuncts: 7 Disjuncts: 3 -- out/eval -- (struct){ input: (string){ string } foo: (_|_){ // [incomplete] foo: non-concrete argument 0: // ./in.cue:4:8 } } -- out/compile -- --- in.cue { input: string foo: 〈import;"encoding/json"〉.Marshal(〈0;input〉) } cue-lang-cue-db9cc73/cue/testdata/fulleval/049_alias_reuse_in_nested_scope.txtar000066400000000000000000000065441474664451600301050ustar00rootroot00000000000000#name: alias reuse in nested scope #evalFull -- in.cue -- #Foo: { let X = or([for k, _ in {} {k}]) connection: [X]: X } #A: { foo: "key" let X = foo a: foo: [X]: X } #B: { foo: string let X = foo a: foo: [X]: X } b: #B & {foo: "key"} -- out/def -- #Foo: { connection: { [or([for k, _ in { ... } { k }])]: or([for k, _ in { ... } { k }]) } } #A: { foo: "key" a: { foo: { ["key"]: "key" } } } #B: { foo: string FOO = foo a: { foo: { [FOO]: FOO } } } b: #B & { foo: "key" } -- out/export -- b: { foo: "key" a: { foo: {} } } -- out/yaml -- b: foo: key a: foo: {} -- out/json -- {"b":{"foo":"key","a":{"foo":{}}}} -- out/legacy-debug -- <0>{#Foo: <1>C{connection: <2>C{[or ([ <3>for k, _ in <4>{} yield <3>.k ])]: <5>(_: string)->or ([ <3>for k, _ in <4>{} yield <3>.k ]), }}, #A: <6>C{foo: "key", a: <7>C{foo: <8>C{["key"]: <9>(_: string)-><10>.foo, }}}, #B: <11>C{foo: string, a: <12>C{foo: <13>C{[string]: <14>(_: string)-><15>.foo, }}}, b: <16>C{foo: "key", a: <17>C{foo: <18>C{["key"]: <19>(_: string)-><20>.foo, }}}} -- out/eval/stats -- Leaks: 10 Freed: 19 Reused: 15 Allocs: 14 Retain: 10 Unifications: 29 Conjuncts: 40 Disjuncts: 29 -- out/evalalpha -- (struct){ #Foo: (#struct){ let X#1 = (_|_){ // [incomplete] empty list in call to or: // ./in.cue:2:10 } connection: (_|_){ // [incomplete] empty list in call to or: // ./in.cue:2:10 } } #A: (#struct){ foo: (string){ "key" } let X#2 = (string){ "key" } a: (#struct){ foo: (#struct){ } } } #B: (#struct){ foo: (string){ string } let X#3 = (string){ string } a: (#struct){ foo: (#struct){ } } } b: (#struct){ foo: (string){ "key" } let X#3 = (string){ "key" } a: (#struct){ foo: (#struct){ } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,7 +4,9 @@ // [incomplete] empty list in call to or: // ./in.cue:2:10 } - connection: (#struct){ + connection: (_|_){ + // [incomplete] empty list in call to or: + // ./in.cue:2:10 } } #A: (#struct){ -- diff/explanation -- The new error is a correct error, as the pattern constraint is invalid. Seems reasonable to report error at connection as well. -- out/eval -- (struct){ #Foo: (#struct){ let X#1 = (_|_){ // [incomplete] empty list in call to or: // ./in.cue:2:10 } connection: (#struct){ } } #A: (#struct){ foo: (string){ "key" } let X#2 = (string){ "key" } a: (#struct){ foo: (#struct){ } } } #B: (#struct){ foo: (string){ string } let X#3 = (string){ string } a: (#struct){ foo: (#struct){ } } } b: (#struct){ foo: (string){ "key" } let X#3 = (string){ "key" } a: (#struct){ foo: (#struct){ } } } } -- out/compile -- --- in.cue { #Foo: { let X#1 = or([ for k, _ in {} { 〈1;k〉 }, ]) connection: { [〈1;let X#1〉]: 〈1;let X#1〉 } } #A: { foo: "key" let X#2 = 〈0;foo〉 a: { foo: { [〈2;let X#2〉]: 〈2;let X#2〉 } } } #B: { foo: string let X#3 = 〈0;foo〉 a: { foo: { [〈2;let X#3〉]: 〈2;let X#3〉 } } } b: (〈0;#B〉 & { foo: "key" }) } cue-lang-cue-db9cc73/cue/testdata/fulleval/050_json_Marshaling_detects_incomplete.txtar000066400000000000000000000020621474664451600314170ustar00rootroot00000000000000#name: json Marshaling detects incomplete #evalFull -- in.cue -- import "encoding/json" a: json.Marshal({a: string}) foo: {a: 3, b: foo.c} b: json.Marshal(foo) -- out/def -- import "encoding/json" a: json.Marshal({ a: string }) foo: { a: 3 b: foo.c } b: json.Marshal(foo) -- out/legacy-debug -- <0>{a: <1>.Marshal (<2>{a: string}), foo: <3>{a: 3, b: <4>.foo.c}, b: <1>.Marshal (<4>.foo)} -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 12 Allocs: 4 Retain: 5 Unifications: 16 Conjuncts: 24 Disjuncts: 21 -- out/eval -- (struct){ a: (_|_){ // [incomplete] cannot convert incomplete value "string" to JSON: // ./in.cue:3:21 } foo: (struct){ a: (int){ 3 } b: (_|_){ // [incomplete] foo.b: undefined field: c: // ./in.cue:5:20 } } b: (_|_){ // [incomplete] foo.b: undefined field: c: // ./in.cue:5:20 } } -- out/compile -- --- in.cue { a: 〈import;"encoding/json"〉.Marshal({ a: string }) foo: { a: 3 b: 〈1;foo〉.c } b: 〈import;"encoding/json"〉.Marshal(〈0;foo〉) } cue-lang-cue-db9cc73/cue/testdata/fulleval/051_detectIncompleteYAML.txtar000066400000000000000000000047641474664451600263360ustar00rootroot00000000000000#name: detectIncompleteYAML #evalFull -- in.cue -- package foobar import yaml "encoding/yaml" #Spec: { _vars: {something: string} data: { #foo: { use: _vars.something } baz: yaml.Marshal(_vars.something) foobar: yaml.Marshal(#foo) } } Val: #Spec & { _vars: something: "var-string" } -- out/def -- package foobar import "encoding/yaml" #Spec: { _vars: { something: string } data: { #foo: { use: _vars.something } baz: yaml.Marshal(_vars.something) foobar: yaml.Marshal(#foo) } } Val: #Spec & { _vars: { something: "var-string" } } -- out/export -- Val: { data: { baz: """ var-string """ foobar: """ use: var-string """ } } -- out/yaml -- Val: data: baz: | var-string foobar: | use: var-string -- out/json -- {"Val":{"data":{"baz":"var-string\n","foobar":"use: var-string\n"}}} -- out/legacy-debug -- <0>{#Spec: <1>C{_vars: <2>C{something: string}, data: <3>C{#foo: <4>C{use: string}, baz: <5>.Marshal (<6>._vars.something), foobar: <5>.Marshal (<7>.#foo)}}, Val: <8>C{_vars: <9>C{something: "var-string"}, data: <10>C{#foo: <11>C{use: "var-string"}, baz: "var-string\n", foobar: "use: var-string\n"}}} -- out/eval/stats -- Leaks: 0 Freed: 17 Reused: 12 Allocs: 5 Retain: 0 Unifications: 17 Conjuncts: 32 Disjuncts: 17 -- out/eval -- (struct){ #Spec: (#struct){ _vars(:foobar): (#struct){ something: (string){ string } } data: (#struct){ #foo: (#struct){ use: (string){ string } } baz: (_|_){ // [incomplete] #Spec.data.baz: non-concrete argument 0: // ./in.cue:11:11 } foobar: (_|_){ // [incomplete] #Spec.data.foobar: error in call to encoding/yaml.Marshal: incomplete value string: // ./in.cue:12:11 // ./in.cue:6:21 } } } Val: (#struct){ _vars(:foobar): (#struct){ something: (string){ "var-string" } } data: (#struct){ #foo: (#struct){ use: (string){ "var-string" } } baz: (string){ "var-string\n" } foobar: (string){ "use: var-string\n" } } } } -- out/compile -- --- in.cue { #Spec: { _vars: { something: string } data: { #foo: { use: 〈2;_vars〉.something } baz: 〈import;"encoding/yaml"〉.Marshal(〈1;_vars〉.something) foobar: 〈import;"encoding/yaml"〉.Marshal(〈0;#foo〉) } } Val: (〈0;#Spec〉 & { _vars: { something: "var-string" } }) } cue-lang-cue-db9cc73/cue/testdata/fulleval/052_detectIncompleteJSON.txtar000066400000000000000000000046271474664451600263440ustar00rootroot00000000000000#name: detectIncompleteJSON #evalFull -- in.cue -- package foobar import "encoding/json" #Spec: { _vars: {something: string} data: { #foo: { use: _vars.something } baz: json.Marshal(_vars.something) foobar: json.Marshal(#foo) } } Val: #Spec & { _vars: something: "var-string" } -- out/def -- package foobar import "encoding/json" #Spec: { _vars: { something: string } data: { #foo: { use: _vars.something } baz: json.Marshal(_vars.something) foobar: json.Marshal(#foo) } } Val: #Spec & { _vars: { something: "var-string" } } -- out/export -- Val: { data: { baz: "\"var-string\"" foobar: "{\"use\":\"var-string\"}" } } -- out/yaml -- Val: data: baz: '"var-string"' foobar: '{"use":"var-string"}' -- out/json -- {"Val":{"data":{"baz":"\"var-string\"","foobar":"{\"use\":\"var-string\"}"}}} -- out/legacy-debug -- <0>{#Spec: <1>C{_vars: <2>C{something: string}, data: <3>C{#foo: <4>C{use: string}, baz: <5>.Marshal (<6>._vars.something), foobar: <5>.Marshal (<7>.#foo)}}, Val: <8>C{_vars: <9>C{something: "var-string"}, data: <10>C{#foo: <11>C{use: "var-string"}, baz: "\"var-string\"", foobar: "{\"use\":\"var-string\"}"}}} -- out/eval/stats -- Leaks: 0 Freed: 17 Reused: 12 Allocs: 5 Retain: 0 Unifications: 17 Conjuncts: 32 Disjuncts: 17 -- out/eval -- (struct){ #Spec: (#struct){ _vars(:foobar): (#struct){ something: (string){ string } } data: (#struct){ #foo: (#struct){ use: (string){ string } } baz: (_|_){ // [incomplete] #Spec.data.baz: non-concrete argument 0: // ./in.cue:11:11 } foobar: (_|_){ // [incomplete] cannot convert incomplete value "string" to JSON: // ./in.cue:6:21 } } } Val: (#struct){ _vars(:foobar): (#struct){ something: (string){ "var-string" } } data: (#struct){ #foo: (#struct){ use: (string){ "var-string" } } baz: (string){ "\"var-string\"" } foobar: (string){ "{\"use\":\"var-string\"}" } } } } -- out/compile -- --- in.cue { #Spec: { _vars: { something: string } data: { #foo: { use: 〈2;_vars〉.something } baz: 〈import;"encoding/json"〉.Marshal(〈1;_vars〉.something) foobar: 〈import;"encoding/json"〉.Marshal(〈0;#foo〉) } } Val: (〈0;#Spec〉 & { _vars: { something: "var-string" } }) } cue-lang-cue-db9cc73/cue/testdata/fulleval/053_issue312.txtar000066400000000000000000000011261474664451600237300ustar00rootroot00000000000000#name: issue312 #evalFull -- in.cue -- for x in [1] { *close({}) | {[_]: null} } -- out/def -- for x in [1] *close({}) | { [string]: null } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/legacy-debug -- <0>{ <1>for _, x in [1] yield <2>{}, (*close (<3>{}) | <4>{[]: <5>(_: string)->null, })} -- out/eval/stats -- Leaks: 2 Freed: 3 Reused: 0 Allocs: 5 Retain: 2 Unifications: 3 Conjuncts: 8 Disjuncts: 5 -- out/eval -- (struct){ |(*(#struct){ }, (struct){ }) } -- out/compile -- --- in.cue { for _, x in [ 1, ] { (*close({})|{ [_]: null }) } } cue-lang-cue-db9cc73/cue/testdata/fulleval/054_issue312.txtar000066400000000000000000000010741474664451600237330ustar00rootroot00000000000000#name: issue312 #evalFull -- in.cue -- y: *1 | {a: 2} for x in [1] {y} -- out/def -- y: *1 | { a: 2 } a: 2 -- out/export -- y: 1 a: 2 -- out/yaml -- y: 1 a: 2 -- out/json -- {"y":1,"a":2} -- out/legacy-debug -- <0>{y: 1, a: 2} -- out/compile -- --- in.cue { y: (*1|{ a: 2 }) for _, x in [ 1, ] { 〈2;y〉 } } -- out/eval/stats -- Leaks: 1 Freed: 8 Reused: 3 Allocs: 6 Retain: 1 Unifications: 5 Conjuncts: 12 Disjuncts: 9 -- out/eval -- (struct){ y: ((int|struct)){ |(*(int){ 1 }, (struct){ a: (int){ 2 } }) } a: (int){ 2 } } cue-lang-cue-db9cc73/cue/testdata/fulleval/055_issue318.txtar000066400000000000000000000031271474664451600237430ustar00rootroot00000000000000#name: issue318 #evalFull -- in.cue -- #T: { arg: x: string out1: "\(arg.x) \(arg.y)" out2: "\(arg.y)" vx: arg.x vy: arg.y } -- out/def -- #T: { arg: { x: string } out1: _|_ // undefined field "y" out2: _|_ // undefined field "y" vx: arg.x vy: _|_ // undefined field "y" } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/legacy-debug -- <0>{#T: <1>C{arg: <2>C{x: string}, out1: _|_(<3>.arg.y:undefined field "y"), out2: _|_(<3>.arg.y:undefined field "y"), vx: string, vy: _|_(<3>.arg.y:undefined field "y")}} -- out/compile -- --- in.cue { #T: { arg: { x: string } out1: "\(〈0;arg〉.x) \(〈0;arg〉.y)" out2: "\(〈0;arg〉.y)" vx: 〈0;arg〉.x vy: 〈0;arg〉.y } } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 4 Allocs: 4 Retain: 0 Unifications: 8 Conjuncts: 9 Disjuncts: 8 -- out/eval -- Errors: #T.out1: invalid interpolation: undefined field: y: ./in.cue:3:8 ./in.cue:3:24 #T.out2: invalid interpolation: undefined field: y: ./in.cue:4:8 ./in.cue:4:15 #T.vy: undefined field: y: ./in.cue:6:12 Result: (_|_){ // [eval] #T: (_|_){ // [eval] arg: (#struct){ x: (string){ string } } out1: (_|_){ // [eval] #T.out1: invalid interpolation: undefined field: y: // ./in.cue:3:8 // ./in.cue:3:24 } out2: (_|_){ // [eval] #T.out2: invalid interpolation: undefined field: y: // ./in.cue:4:8 // ./in.cue:4:15 } vx: (string){ string } vy: (_|_){ // [eval] #T.vy: undefined field: y: // ./in.cue:6:12 } } } cue-lang-cue-db9cc73/cue/testdata/interpolation/000077500000000000000000000000001474664451600217545ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/interpolation/041_interpolation.txtar000066400000000000000000000026731474664451600263230ustar00rootroot00000000000000#name: interpolation #evalPartial -- in.cue -- a: "\(4)" b: "one \(a) two \( a+c )" c: "one" d: "\(r)" u: "\(_)" r: _ e: "\([])" -- out/def -- a: "4" b: "one 4 two 4one" c: "one" d: "\(r)" r: _ u: "\(_)" e: _|_ // expression in interpolation must evaluate to a number kind or string (found list) -- out/legacy-debug -- <0>{a: "4", b: "one 4 two 4one", c: "one", d: ""+<1>.r+"", r: _, u: ""+_+"", e: _|_([]:expression in interpolation must evaluate to a number kind or string (found list))} -- out/compile -- --- in.cue { a: "\(4)" b: "one \(〈0;a〉) two \((〈0;a〉 + 〈0;c〉))" c: "one" d: "\(〈0;r〉)" u: "\(_)" r: _ e: "\([])" } -- out/eval/stats -- Leaks: 1 Freed: 8 Reused: 6 Allocs: 3 Retain: 12 Unifications: 9 Conjuncts: 16 Disjuncts: 19 -- out/eval -- Errors: e: invalid interpolation: cannot use [] (type list) as type (bool|string|bytes|number): ./in.cue:7:4 ./in.cue:7:7 Result: (_|_){ // [eval] a: (string){ "4" } b: (string){ "one 4 two 4one" } c: (string){ "one" } d: (_|_){ // [incomplete] d: invalid interpolation: non-concrete value _ (type _): // ./in.cue:4:4 } u: (_|_){ // [incomplete] u: invalid interpolation: non-concrete value _ (type _): // ./in.cue:5:4 // ./in.cue:5:7 } r: (_){ _ } e: (_|_){ // [eval] e: invalid interpolation: cannot use [] (type list) as type (bool|string|bytes|number): // ./in.cue:7:4 // ./in.cue:7:7 } } cue-lang-cue-db9cc73/cue/testdata/interpolation/042_multiline_interpolation.txtar000066400000000000000000000044741474664451600304070ustar00rootroot00000000000000#name: multiline interpolation #evalPartial -- in.cue -- a1: """ before \(4) after """ a2: """ before \(4) """ a3: """ \(4) after """ a4: """ \(4) """ m1: """ before \( 4) after """ m2: """ before \( 4) """ m3: """ \( 4) after """ m4: """ \( 4) """ -- out/def -- a1: """ before 4 after """ a2: """ before 4 """ a3: """ 4 after """ a4: """ 4 """ m1: """ before 4 after """ m2: """ before 4 """ m3: """ 4 after """ m4: """ 4 """ -- out/export -- a1: """ before 4 after """ a2: """ before 4 """ a3: """ 4 after """ a4: """ 4 """ m1: """ before 4 after """ m2: """ before 4 """ m3: """ 4 after """ m4: """ 4 """ -- out/yaml -- a1: |- before 4 after a2: | before 4 a3: |2- 4 after a4: |2 4 m1: |- before 4 after m2: | before 4 m3: |2- 4 after m4: |2 4 -- out/json -- {"a1":"before\n4\nafter","a2":"before\n4\n","a3":"\n4\nafter","a4":"\n4\n","m1":"before\n4\nafter","m2":"before\n4\n","m3":"\n4\nafter","m4":"\n4\n"} -- out/legacy-debug -- <0>{a1: "before\n4\nafter", a2: "before\n4\n", a3: "\n4\nafter", a4: "\n4\n", m1: "before\n4\nafter", m2: "before\n4\n", m3: "\n4\nafter", m4: "\n4\n"} -- out/compile -- --- in.cue { a1: "before \(4) after" a2: "before \(4) " a3: " \(4) after" a4: " \(4) " m1: "before \(4) after" m2: "before \(4) " m3: " \(4) after" m4: " \(4) " } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 7 Allocs: 2 Retain: 0 Unifications: 9 Conjuncts: 9 Disjuncts: 9 -- out/eval -- (struct){ a1: (string){ "before\n4\nafter" } a2: (string){ "before\n4\n" } a3: (string){ "\n4\nafter" } a4: (string){ "\n4\n" } m1: (string){ "before\n4\nafter" } m2: (string){ "before\n4\n" } m3: (string){ "\n4\nafter" } m4: (string){ "\n4\n" } } cue-lang-cue-db9cc73/cue/testdata/interpolation/incomplete.txtar000066400000000000000000000014761474664451600252070ustar00rootroot00000000000000Issue #553 -- in.cue -- a: "foo" b: "boo" commands: { #c: { help: "help!" } } out: """ a is \(a) b is \(b) c is \(commands.#c.help) d is \(commands.#d.help) """ -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 3 Allocs: 4 Retain: 0 Unifications: 7 Conjuncts: 11 Disjuncts: 7 -- out/eval -- (struct){ a: (string){ "foo" } b: (string){ "boo" } commands: (struct){ #c: (#struct){ help: (string){ "help!" } } } out: (_|_){ // [incomplete] out: invalid interpolation: undefined field: #d: // ./in.cue:8:6 // ./in.cue:13:21 } } -- out/compile -- --- in.cue { a: "foo" b: "boo" commands: { #c: { help: "help!" } } out: "a is \(〈0;a〉) b is \(〈0;b〉) c is \(〈0;commands〉.#c.help) d is \(〈0;commands〉.#d.help)" } cue-lang-cue-db9cc73/cue/testdata/interpolation/issue487.txtar000066400000000000000000000023561474664451600244410ustar00rootroot00000000000000-- in.cue -- t1: { #R: { pos: uint name: "hello_\(pos)" } a: #R & {pos: 67} } t2: { #R: { pos: string name: "hello_\(pos)" } a: #R & {pos: "a"} } -- out/eval/stats -- Leaks: 0 Freed: 15 Reused: 11 Allocs: 4 Retain: 0 Unifications: 15 Conjuncts: 29 Disjuncts: 15 -- out/eval -- (struct){ t1: (struct){ #R: (#struct){ pos: (int){ &(>=0, int) } name: (_|_){ // [incomplete] t1.#R.name: invalid interpolation: non-concrete value >=0 & int (type int): // ./in.cue:4:9 } } a: (#struct){ pos: (int){ 67 } name: (string){ "hello_67" } } } t2: (struct){ #R: (#struct){ pos: (string){ string } name: (_|_){ // [incomplete] t2.#R.name: invalid interpolation: non-concrete value string (type string): // ./in.cue:11:9 // ./in.cue:10:9 } } a: (#struct){ pos: (string){ "a" } name: (string){ "hello_a" } } } } -- out/compile -- --- in.cue { t1: { #R: { pos: &(int, >=0) name: "hello_\(〈0;pos〉)" } a: (〈0;#R〉 & { pos: 67 }) } t2: { #R: { pos: string name: "hello_\(〈0;pos〉)" } a: (〈0;#R〉 & { pos: "a" }) } } cue-lang-cue-db9cc73/cue/testdata/interpolation/scalars.txtar000066400000000000000000000021371474664451600244730ustar00rootroot00000000000000-- in.cue -- bool1: "1+1=2: \(true)" bool1: "1+1=2: \(true)" bool2: "1+1=1: \(false)" // one replacement character b1: 'a\xED\x95a' bytes1s: "\(b1)" bytes1b: '\(b1)' // two replacement characters b2: 'a\x80\x95a' bytes2s: "\(b2)" bytes2b: '\(b2)' // preserve precision n1: "\(1) \(2.00)" // but normalize representation n2: "\(1e2)" -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 9 Allocs: 2 Retain: 0 Unifications: 11 Conjuncts: 12 Disjuncts: 11 -- out/eval -- (struct){ bool1: (string){ "1+1=2: true" } bool2: (string){ "1+1=1: false" } b1: (bytes){ 'a\xed\x95a' } bytes1s: (string){ "a�a" } bytes1b: (bytes){ 'a\xed\x95a' } b2: (bytes){ 'a\x80\x95a' } bytes2s: (string){ "a��a" } bytes2b: (bytes){ 'a\x80\x95a' } n1: (string){ "1 2.00" } n2: (string){ "1E+2" } } -- out/compile -- --- in.cue { bool1: "1+1=2: \(true)" bool1: "1+1=2: \(true)" bool2: "1+1=1: \(false)" b1: 'a\xed\x95a' bytes1s: "\(〈0;b1〉)" bytes1b: '\(〈0;b1〉)' b2: 'a\x80\x95a' bytes2s: "\(〈0;b2〉)" bytes2b: '\(〈0;b2〉)' n1: "\(1) \(2.00)" n2: "\(1E+2)" } cue-lang-cue-db9cc73/cue/testdata/lists/000077500000000000000000000000001474664451600202235ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/lists/019_list_types.txtar000066400000000000000000000067371474664451600241140ustar00rootroot00000000000000#name: list types #evalPartial -- in.cue -- import "list" l0: list.Repeat([int], 3) l0: [1, 2, 3] l2: [...{a: int}] l2: [{a: 1}, {a: 2, b: 3}] // TODO: work out a decent way to specify length ranges of lists. // l3: <=10*[int] // l3: [1, 2, 3, ...] s1: (list.Repeat([int], 6))[2:3] s2: [0, 2, 3][1:2] i1: (list.Repeat([int], 6))[2] i2: [0, 2, 3][2] t0: [...{a: 8}] t0: [{}] t1: [...] t1: [...int] e0: list.Repeat([{}], 2) e0: [{}] e1: [...int] e1: [...float] -- out/def -- l0: [1, 2, 3] l2: [{ a: 1 }, { a: 2 b: 3 }] s1: [int] s2: [2] i1: [int, int, int, int, int, int][2] i2: 3 t0: [{ a: 8 }] t1: [...int] e0: _|_ // conflicting list lengths: conflicting values 2 and 1 e1: [..._|_ // conflicting values int and float (mismatched types int and float), ] -- out/legacy-debug -- <0>{l0: [1,2,3], l2: [<1>{a: 1},<2>{a: 2, b: 3}], s1: [int], s2: [2], i1: int, i2: 3, t0: [<3>{a: 8}], t1: [, ...int], e0: _|_(([<4>{},<4>{}] & [<5>{}]):conflicting list lengths: conflicting values 2 and 1), e1: [, ..._|_((int & float):conflicting values int and float (mismatched types int and float))]} -- out/compile -- --- in.cue { l0: 〈import;list〉.Repeat([ int, ], 3) l0: [ 1, 2, 3, ] l2: [ ...{ a: int }, ] l2: [ { a: 1 }, { a: 2 b: 3 }, ] s1: 〈import;list〉.Repeat([ int, ], 6)[2:3] s2: [ 0, 2, 3, ][1:2] i1: 〈import;list〉.Repeat([ int, ], 6)[2] i2: [ 0, 2, 3, ][2] t0: [ ...{ a: 8 }, ] t0: [ {}, ] t1: [ ..., ] t1: [ ...int, ] e0: 〈import;list〉.Repeat([ {}, ], 2) e0: [ {}, ] e1: [ ...int, ] e1: [ ...float, ] } -- out/eval/stats -- Leaks: 3 Freed: 33 Reused: 29 Allocs: 7 Retain: 7 Unifications: 36 Conjuncts: 59 Disjuncts: 39 -- out/evalalpha -- Errors: e0: incompatible list lengths (1 and 2): _:1:2 Result: (_|_){ // [eval] l0: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } l2: (#list){ 0: (struct){ a: (int){ 1 } } 1: (struct){ a: (int){ 2 } b: (int){ 3 } } } s1: (#list){ 0: (int){ int } } s2: (#list){ 0: (int){ 2 } } i1: (int){ int } i2: (int){ 3 } t0: (#list){ 0: (struct){ a: (int){ 8 } } } t1: (list){ } e0: (_|_){ // [eval] e0: incompatible list lengths (1 and 2): // _:1:2 0: (struct){ } 1: (struct){ } } e1: (list){ } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,5 +1,6 @@ Errors: -e0: incompatible list lengths (1 and 2) +e0: incompatible list lengths (1 and 2): + _:1:2 Result: (_|_){ @@ -34,7 +35,8 @@ t1: (list){ } e0: (_|_){ - // [eval] e0: incompatible list lengths (1 and 2) + // [eval] e0: incompatible list lengths (1 and 2): + // _:1:2 0: (struct){ } 1: (struct){ -- out/eval -- Errors: e0: incompatible list lengths (1 and 2) Result: (_|_){ // [eval] l0: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } } l2: (#list){ 0: (struct){ a: (int){ 1 } } 1: (struct){ a: (int){ 2 } b: (int){ 3 } } } s1: (#list){ 0: (int){ int } } s2: (#list){ 0: (int){ 2 } } i1: (int){ int } i2: (int){ 3 } t0: (#list){ 0: (struct){ a: (int){ 8 } } } t1: (list){ } e0: (_|_){ // [eval] e0: incompatible list lengths (1 and 2) 0: (struct){ } 1: (struct){ } } e1: (list){ } } cue-lang-cue-db9cc73/cue/testdata/lists/020_list_compilefail.txtar000066400000000000000000000025541474664451600252150ustar00rootroot00000000000000#name: list arithmetic #evalPartial -- in.cue -- l3: <=2 * [] l4: <=2 * [int] l5: <=2 * (int * [int]) b: <=5 * [int] b: [1, 2, ...] c: (>=3 & <=5) * [int] c: [1, 2, ...] d: >=2 * [int] d: [1, 2, ...] -- out/compile -- l3: invalid operand <=2 ('*' requires concrete value): ./in.cue:1:5 l4: invalid operand <=2 ('*' requires concrete value): ./in.cue:2:5 l5: invalid operand <=2 ('*' requires concrete value): ./in.cue:3:5 l5: invalid operand int ('*' requires concrete value): ./in.cue:3:12 b: invalid operand <=5 ('*' requires concrete value): ./in.cue:4:5 d: invalid operand >=2 ('*' requires concrete value): ./in.cue:8:4 --- in.cue { l3: (<=2 * []) l4: (<=2 * [ int, ]) l5: (<=2 * (int * [ int, ])) b: (<=5 * [ int, ]) b: [ 1, 2, ..., ] c: ((>=3 & <=5) * [ int, ]) c: [ 1, 2, ..., ] d: (>=2 * [ int, ]) d: [ 1, 2, ..., ] } -- out/eval -- l3: invalid operand <=2 ('*' requires concrete value): ./in.cue:1:5 l4: invalid operand <=2 ('*' requires concrete value): ./in.cue:2:5 l5: invalid operand <=2 ('*' requires concrete value): ./in.cue:3:5 l5: invalid operand int ('*' requires concrete value): ./in.cue:3:12 b: invalid operand <=5 ('*' requires concrete value): ./in.cue:4:5 d: invalid operand >=2 ('*' requires concrete value): ./in.cue:8:4 cue-lang-cue-db9cc73/cue/testdata/lists/021_list_equality.txtar000066400000000000000000000167231474664451600245720ustar00rootroot00000000000000#name: list equality #evalPartial -- in.cue -- eq0: [] == [] eq1: [...] == [] eq2: [] == [...] eq3: [...] == [...] eq4: [1] == [1] eq5: [1, ...] == [1] eq6: [1] == [1, ...] eq7: [1, ...] == [1, ...] eq8: [1, 2] == [1, 2] eq9: [1, 2, ...] == [1, 2] eq10: [1, 2] == [1, 2, ...] eq11: [1, 2, ...] == [1, 2, ...] ne0: [] != [] ne1: [...] != [] ne2: [] != [...] ne3: [...] != [...] ne4: [1] != [1] ne5: [1, ...] != [1] ne6: [1] != [1, ...] ne7: [1, ...] != [1, ...] ne8: [1, 2] != [1, 2] ne9: [1, 2, ...] != [1, 2] ne10: [1, 2] != [1, 2, ...] ne11: [1, 2, ...] != [1, 2, ...] feq0: [] == [1] feq1: [...] == [1] feq2: [] == [1, ...] feq3: [...] == [1, ...] feq4: [1] == [] feq5: [1, ...] == [] feq6: [1] == [...] feq7: [1, ...] == [...] feq8: [1, 2] == [1] feq9: [1, ...] == [1, 2] feq10: [1, 2] == [1, ...] feq11: [1, ...] == [1, 2, ...] fne0: [] != [1] fne1: [...] != [1] fne2: [] != [1, ...] fne3: [1, ...] != [1, ...] fne4: [1] != [] fne5: [1, ...] != [] fne6: [1] != [...] fne7: [1, ...] != [...] fne8: [1, 2] != [1] fne9: [1, ...] != [1, 2] fne10: [1, 2] != [1, ...] fne11: [1, ...] != [1, 2, ...] -- out/def -- eq0: true eq1: true eq2: true eq3: true eq4: true eq5: true eq6: true eq7: true eq8: true eq9: true eq10: true eq11: true ne0: true ne1: true ne2: true ne3: true ne4: false ne5: false ne6: false ne7: false ne8: false ne9: false ne10: false ne11: false feq0: false feq1: false feq2: false feq3: false feq4: false feq5: false feq6: false feq7: false feq8: false feq9: false feq10: false feq11: false fne0: true fne1: true fne2: true fne3: false fne4: true fne5: true fne6: true fne7: true fne8: true fne9: true fne10: true fne11: true -- out/export -- eq0: true eq1: true eq2: true eq3: true eq4: true eq5: true eq6: true eq7: true eq8: true eq9: true eq10: true eq11: true ne0: true ne1: true ne2: true ne3: true ne4: false ne5: false ne6: false ne7: false ne8: false ne9: false ne10: false ne11: false feq0: false feq1: false feq2: false feq3: false feq4: false feq5: false feq6: false feq7: false feq8: false feq9: false feq10: false feq11: false fne0: false fne1: false fne2: false fne3: false fne4: false fne5: false fne6: false fne7: false fne8: false fne9: false fne10: false fne11: false -- out/yaml -- eq0: true eq1: true eq2: true eq3: true eq4: true eq5: true eq6: true eq7: true eq8: true eq9: true eq10: true eq11: true ne0: true ne1: true ne2: true ne3: true ne4: false ne5: false ne6: false ne7: false ne8: false ne9: false ne10: false ne11: false feq0: false feq1: false feq2: false feq3: false feq4: false feq5: false feq6: false feq7: false feq8: false feq9: false feq10: false feq11: false fne0: false fne1: false fne2: false fne3: false fne4: false fne5: false fne6: false fne7: false fne8: false fne9: false fne10: false fne11: false -- out/json -- {"eq0":true,"eq1":true,"eq2":true,"eq3":true,"eq4":true,"eq5":true,"eq6":true,"eq7":true,"eq8":true,"eq9":true,"eq10":true,"eq11":true,"ne0":true,"ne1":true,"ne2":true,"ne3":true,"ne4":false,"ne5":false,"ne6":false,"ne7":false,"ne8":false,"ne9":false,"ne10":false,"ne11":false,"feq0":false,"feq1":false,"feq2":false,"feq3":false,"feq4":false,"feq5":false,"feq6":false,"feq7":false,"feq8":false,"feq9":false,"feq10":false,"feq11":false,"fne0":false,"fne1":false,"fne2":false,"fne3":false,"fne4":false,"fne5":false,"fne6":false,"fne7":false,"fne8":false,"fne9":false,"fne10":false,"fne11":false} -- out/legacy-debug -- <0>{eq0: true, eq1: true, eq2: true, eq3: true, eq4: true, eq5: true, eq6: true, eq7: true, eq8: true, eq9: true, eq10: true, eq11: true, ne0: true, ne1: true, ne2: true, ne3: true, ne4: false, ne5: false, ne6: false, ne7: false, ne8: false, ne9: false, ne10: false, ne11: false, feq0: false, feq1: false, feq2: false, feq3: false, feq4: false, feq5: false, feq6: false, feq7: false, feq8: false, feq9: false, feq10: false, feq11: false, fne0: false, fne1: false, fne2: false, fne3: false, fne4: false, fne5: false, fne6: false, fne7: false, fne8: false, fne9: false, fne10: false, fne11: false} -- out/compile -- --- in.cue { eq0: ([] == []) eq1: ([ ..., ] == []) eq2: ([] == [ ..., ]) eq3: ([ ..., ] == [ ..., ]) eq4: ([ 1, ] == [ 1, ]) eq5: ([ 1, ..., ] == [ 1, ]) eq6: ([ 1, ] == [ 1, ..., ]) eq7: ([ 1, ..., ] == [ 1, ..., ]) eq8: ([ 1, 2, ] == [ 1, 2, ]) eq9: ([ 1, 2, ..., ] == [ 1, 2, ]) eq10: ([ 1, 2, ] == [ 1, 2, ..., ]) eq11: ([ 1, 2, ..., ] == [ 1, 2, ..., ]) ne0: ([] != []) ne1: ([ ..., ] != []) ne2: ([] != [ ..., ]) ne3: ([ ..., ] != [ ..., ]) ne4: ([ 1, ] != [ 1, ]) ne5: ([ 1, ..., ] != [ 1, ]) ne6: ([ 1, ] != [ 1, ..., ]) ne7: ([ 1, ..., ] != [ 1, ..., ]) ne8: ([ 1, 2, ] != [ 1, 2, ]) ne9: ([ 1, 2, ..., ] != [ 1, 2, ]) ne10: ([ 1, 2, ] != [ 1, 2, ..., ]) ne11: ([ 1, 2, ..., ] != [ 1, 2, ..., ]) feq0: ([] == [ 1, ]) feq1: ([ ..., ] == [ 1, ]) feq2: ([] == [ 1, ..., ]) feq3: ([ ..., ] == [ 1, ..., ]) feq4: ([ 1, ] == []) feq5: ([ 1, ..., ] == []) feq6: ([ 1, ] == [ ..., ]) feq7: ([ 1, ..., ] == [ ..., ]) feq8: ([ 1, 2, ] == [ 1, ]) feq9: ([ 1, ..., ] == [ 1, 2, ]) feq10: ([ 1, 2, ] == [ 1, ..., ]) feq11: ([ 1, ..., ] == [ 1, 2, ..., ]) fne0: ([] != [ 1, ]) fne1: ([ ..., ] != [ 1, ]) fne2: ([] != [ 1, ..., ]) fne3: ([ 1, ..., ] != [ 1, ..., ]) fne4: ([ 1, ] != []) fne5: ([ 1, ..., ] != []) fne6: ([ 1, ] != [ ..., ]) fne7: ([ 1, ..., ] != [ ..., ]) fne8: ([ 1, 2, ] != [ 1, ]) fne9: ([ 1, ..., ] != [ 1, 2, ]) fne10: ([ 1, 2, ] != [ 1, ..., ]) fne11: ([ 1, ..., ] != [ 1, 2, ..., ]) } -- out/eval/stats -- Leaks: 0 Freed: 234 Reused: 229 Allocs: 5 Retain: 96 Unifications: 234 Conjuncts: 234 Disjuncts: 330 -- out/eval -- (struct){ eq0: (bool){ true } eq1: (bool){ true } eq2: (bool){ true } eq3: (bool){ true } eq4: (bool){ true } eq5: (bool){ true } eq6: (bool){ true } eq7: (bool){ true } eq8: (bool){ true } eq9: (bool){ true } eq10: (bool){ true } eq11: (bool){ true } ne0: (bool){ false } ne1: (bool){ false } ne2: (bool){ false } ne3: (bool){ false } ne4: (bool){ false } ne5: (bool){ false } ne6: (bool){ false } ne7: (bool){ false } ne8: (bool){ false } ne9: (bool){ false } ne10: (bool){ false } ne11: (bool){ false } feq0: (bool){ false } feq1: (bool){ false } feq2: (bool){ false } feq3: (bool){ false } feq4: (bool){ false } feq5: (bool){ false } feq6: (bool){ false } feq7: (bool){ false } feq8: (bool){ false } feq9: (bool){ false } feq10: (bool){ false } feq11: (bool){ false } fne0: (bool){ true } fne1: (bool){ true } fne2: (bool){ true } fne3: (bool){ false } fne4: (bool){ true } fne5: (bool){ true } fne6: (bool){ true } fne7: (bool){ true } fne8: (bool){ true } fne9: (bool){ true } fne10: (bool){ true } fne11: (bool){ true } } cue-lang-cue-db9cc73/cue/testdata/packages/000077500000000000000000000000001474664451600206435ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/packages/builtin.txtar000066400000000000000000000002541474664451600233760ustar00rootroot00000000000000-- x.cue -- import "x/y" foo: [ y, ] -- out/eval -- builtin package "x/y" undefined: ./x.cue:1:8 -- out/compile -- --- x.cue { foo: [ 〈import;"x/y"〉, ] } cue-lang-cue-db9cc73/cue/testdata/packages/embed.txtar000066400000000000000000000020141474664451600230000ustar00rootroot00000000000000exec cue eval ./pkg:foo -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- package foo import "mod.test/pkg:bar" bar z: 3 -- pkg/bar.cue -- package bar import "mod.test/pkg:baz" foo: { baz y: 2 } foo -- pkg/baz.cue -- package baz x: 1 -- out/eval/stats -- Leaks: 2 Freed: 9 Reused: 6 Allocs: 5 Retain: 4 Unifications: 11 Conjuncts: 25 Disjuncts: 13 -- out/evalalpha -- (struct){ z: (int){ 3 } foo: (struct){ y: (int){ 2 } x: (int){ 1 } } y: (int){ 2 } x: (int){ 1 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,9 @@ (struct){ + z: (int){ 3 } foo: (struct){ - x: (int){ 1 } y: (int){ 2 } + x: (int){ 1 } } - x: (int){ 1 } y: (int){ 2 } - z: (int){ 3 } + x: (int){ 1 } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ foo: (struct){ x: (int){ 1 } y: (int){ 2 } } x: (int){ 1 } y: (int){ 2 } z: (int){ 3 } } -- out/compile -- --- in.cue { 〈import;"mod.test/pkg:bar"〉 z: 3 } cue-lang-cue-db9cc73/cue/testdata/packages/issue398.txtar000066400000000000000000000014611474664451600233250ustar00rootroot00000000000000-- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- foo.cue -- package foo import "mod.test/pkg:bar" bar zz: 3 -- pkg/bar.cue -- package bar import "mod.test/pkg:baz" baz yy: 2 -- pkg/baz.cue -- package baz xx: 1 -- out/eval/stats -- Leaks: 1 Freed: 6 Reused: 3 Allocs: 4 Retain: 2 Unifications: 7 Conjuncts: 13 Disjuncts: 8 -- out/evalalpha -- (struct){ zz: (int){ 3 } yy: (int){ 2 } xx: (int){ 1 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,5 +1,5 @@ (struct){ - xx: (int){ 1 } - yy: (int){ 2 } zz: (int){ 3 } + yy: (int){ 2 } + xx: (int){ 1 } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ xx: (int){ 1 } yy: (int){ 2 } zz: (int){ 3 } } -- out/compile -- --- foo.cue { 〈import;"mod.test/pkg:bar"〉 zz: 3 } cue-lang-cue-db9cc73/cue/testdata/packages/sub.txtar000066400000000000000000000010501474664451600225140ustar00rootroot00000000000000exec cue eval ./pkg:foo -- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- package test import pkg2 "mod.test/foo/pkg1" #pkg1: pkg2.Object "Hello \(#pkg1)!" -- foo/pkg1/file.cue -- package pkg1 Object: "World" -- out/eval/stats -- Leaks: 2 Freed: 2 Reused: 0 Allocs: 4 Retain: 3 Unifications: 4 Conjuncts: 5 Disjuncts: 4 -- out/eval -- (string){ "Hello World!" #pkg1: (string){ "World" } } -- out/compile -- --- in.cue { #pkg1: 〈import;"mod.test/foo/pkg1"〉.Object "Hello \(〈0;#pkg1〉)!" } cue-lang-cue-db9cc73/cue/testdata/readme.md000066400000000000000000000034641474664451600206530ustar00rootroot00000000000000# CUE Test Suite This directory contains a test suite for testing the CUE language. This is only intended to test language evaluation and exporting. Eventually it will also contains tests for parsing and formatting. It is not intended to cover testing of the API itself. ## Overview ### Work in progress The tests are currently converted from various internal Go tests and the grouping reflect properties of the current implementation. Once the transition to the new implementation is completed, tests should be reordered along more logical lines: such as literals, expressions, references, cycles, etc. ## Forseen Structure The txtar format allows a collection of files to be defined. Any .cue file is used as an input. The out/* files, which should not have an extension, define outputs for various tests. A test definition is active for a certain test if it contains output for this test. The comments section of the txtar file may contain additional control inputs for a test. Each line that starts with a `#` immediately followed by a letter or digit is specially interpreted. These can be boolean tags (`#foo`) or a key-value pair (`#key: value`), where the value can be a free-form string. A line starting with `#` followed by a space is interpreted as a comment. Lines not starting with a `#` are for interpretation by the testscript package. This organization allows the same test sets to be used for the testing of tooling as well as internal libraries. ## Common options - `#skip`: skip this test case for all tests - `#skip-{name}`: skip this test for the namesake test - `#todo-{name}`: skip this test for the namesake test, but run it if the `--todo` flag is specified. ## Tests ### cue/internal/compile Compiles all *.cue files and prints the debug string of the internal representation. This is not valid CUE.cue-lang-cue-db9cc73/cue/testdata/references/000077500000000000000000000000001474664451600212065ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/references/embed_self.txtar000066400000000000000000000003741474664451600243630ustar00rootroot00000000000000-- in.cue -- Foo: { } Foo -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 1 Unifications: 2 Conjuncts: 4 Disjuncts: 3 -- out/eval -- (struct){ Foo: (struct){ } } -- out/compile -- --- in.cue { Foo: {} 〈0;Foo〉 } cue-lang-cue-db9cc73/cue/testdata/references/errors.txtar000066400000000000000000000045361474664451600236160ustar00rootroot00000000000000-- references.cue -- missingField: { a: {} r: a.b } missingFieldClosed: { #a: {} r: #a.b } missingFieldNested: { a: {} // Must refer to `b` in error r: a.b.c } missingFieldNestedClosed: { #a: {} // Must refer to `d` in error r: #a.d.c } missingFieldNestedInInterpolation: { a: {} // Must refer to `b` in error r1: "\(a.b.c)" // Must refer to `d` in error: in case only one error is shown for a // a location, ensure it doesn't alphabetically sort and pick `c` instead. r2: "\(a.d.c)" } -- out/eval/stats -- Leaks: 0 Freed: 17 Reused: 14 Allocs: 3 Retain: 0 Unifications: 17 Conjuncts: 29 Disjuncts: 17 -- out/eval -- Errors: missingFieldClosed.r: undefined field: b: ./references.cue:8:8 missingFieldNestedClosed.r: undefined field: d: ./references.cue:21:8 Result: (_|_){ // [eval] missingField: (struct){ a: (struct){ } r: (_|_){ // [incomplete] missingField.r: undefined field: b: // ./references.cue:3:7 } } missingFieldClosed: (_|_){ // [eval] #a: (#struct){ } r: (_|_){ // [eval] missingFieldClosed.r: undefined field: b: // ./references.cue:8:8 } } missingFieldNested: (struct){ a: (struct){ } r: (_|_){ // [incomplete] missingFieldNested.r: undefined field: b: // ./references.cue:14:7 } } missingFieldNestedClosed: (_|_){ // [eval] #a: (#struct){ } r: (_|_){ // [eval] missingFieldNestedClosed.r: undefined field: d: // ./references.cue:21:8 } } missingFieldNestedInInterpolation: (struct){ a: (struct){ } r1: (_|_){ // [incomplete] missingFieldNestedInInterpolation.r1: invalid interpolation: undefined field: b: // ./references.cue:27:6 // ./references.cue:27:11 } r2: (_|_){ // [incomplete] missingFieldNestedInInterpolation.r2: invalid interpolation: undefined field: d: // ./references.cue:30:6 // ./references.cue:30:11 } } } -- out/compile -- --- references.cue { missingField: { a: {} r: 〈0;a〉.b } missingFieldClosed: { #a: {} r: 〈0;#a〉.b } missingFieldNested: { a: {} r: 〈0;a〉.b.c } missingFieldNestedClosed: { #a: {} r: 〈0;#a〉.d.c } missingFieldNestedInInterpolation: { a: {} r1: "\(〈0;a〉.b.c)" r2: "\(〈0;a〉.d.c)" } } cue-lang-cue-db9cc73/cue/testdata/references/incomplete.txtar000066400000000000000000000036011474664451600244310ustar00rootroot00000000000000-- in.cue -- comprehensions: { a: {} b: { if a.b { } } c: { for x in a.b {x} } } openStruct: { a: {} b: a.c } selectFromTop: { top: _ a: top.foo } indexOnTop: { top: _ a: top[2] } incompleteIndex: { top: _ a: [1][top] } -- out/eval/stats -- Leaks: 1 Freed: 17 Reused: 14 Allocs: 4 Retain: 1 Unifications: 18 Conjuncts: 26 Disjuncts: 18 -- out/eval -- Errors: incompleteIndex.a: invalid index top (invalid type _): ./in.cue:29:7 ./in.cue:29:11 Result: (_|_){ // [eval] comprehensions: (struct){ a: (struct){ } b: (_|_){ // [incomplete] comprehensions.b: undefined field: b: // ./in.cue:4:8 } c: (_|_){ // [incomplete] comprehensions.c: undefined field: b: // ./in.cue:8:14 } } openStruct: (struct){ a: (struct){ } b: (_|_){ // [incomplete] openStruct.b: undefined field: c: // ./in.cue:14:7 } } selectFromTop: (struct){ top: (_){ _ } a: (_|_){ // [incomplete] selectFromTop.a: top.foo undefined as top is incomplete (type _): // ./in.cue:19:7 } } indexOnTop: (struct){ top: (_){ _ } a: (_|_){ // [incomplete] indexOnTop.a: top[2] undefined as top is incomplete (type _): // ./in.cue:24:7 } } incompleteIndex: (_|_){ // [eval] top: (_){ _ } a: (_|_){ // [eval] incompleteIndex.a: invalid index top (invalid type _): // ./in.cue:29:7 // ./in.cue:29:11 } } } -- out/compile -- --- in.cue { comprehensions: { a: {} b: { if 〈1;a〉.b {} } c: { for _, x in 〈1;a〉.b { 〈1;x〉 } } } openStruct: { a: {} b: 〈0;a〉.c } selectFromTop: { top: _ a: 〈0;top〉.foo } indexOnTop: { top: _ a: 〈0;top〉[2] } incompleteIndex: { top: _ a: [ 1, ][〈0;top〉] } } cue-lang-cue-db9cc73/cue/testdata/references/index.txtar000066400000000000000000000210041474664451600233760ustar00rootroot00000000000000-- in.cue -- intIndex: [2][0] stringIndex: {foo: "bar"}["foo"] stringOfNumberIndex: {"3": 3}["3"] indexToDefault: (*[0] | {})[0] outOfBoundsDisjunction: (*[] | {})[1] // Ensure these are errors. indexDoesNotDistribute: (*[] | [1])[0] doesNotDistributeType: { l: [] a: (*l | {"3": 3})["3"] } stringIndexToList: [2][""] indexOutOfBounds2: 2[2] booleanIndex: [][true] indexOutOfBounds3: [1, 2, 3][4] negativeIndex: [1, 2, 3][-1] varIndexTooLarge: { n: 3 a: [1, 2, 3][n] } varNegativeIndex: { n: -1 a: [1, 2, 3][n] } -- out/eval/stats -- Leaks: 12 Freed: 36 Reused: 33 Allocs: 15 Retain: 12 Unifications: 40 Conjuncts: 50 Disjuncts: 45 -- out/evalalpha -- Errors: outOfBoundsDisjunction: index out of range [1] with length 0: ./in.cue:7:36 indexDoesNotDistribute: index out of range [0] with length 0: ./in.cue:10:37 doesNotDistributeType.a: undefined field: "3": ./in.cue:13:21 stringIndexToList: undefined field: "": ./in.cue:16:24 indexOutOfBounds2: invalid operand 2 (found int, want list or struct): ./in.cue:17:20 booleanIndex: invalid index true (invalid type bool): ./in.cue:18:20 ./in.cue:18:23 indexOutOfBounds3: index out of range [4] with length 3: ./in.cue:19:30 negativeIndex: invalid index -1 (index must be non-negative): ./in.cue:20:20 ./in.cue:20:30 varIndexTooLarge.a: index out of range [3] with length 3: ./in.cue:24:15 varNegativeIndex.a: index n out of range [-1]: ./in.cue:29:5 ./in.cue:28:5 ./in.cue:29:15 Result: (_|_){ // [eval] intIndex: (int){ 2 } stringIndex: (string){ "bar" } stringOfNumberIndex: (int){ 3 } indexToDefault: (int){ 0 } outOfBoundsDisjunction: (_|_){ // [eval] outOfBoundsDisjunction: index out of range [1] with length 0: // ./in.cue:7:36 } indexDoesNotDistribute: (_|_){ // [eval] indexDoesNotDistribute: index out of range [0] with length 0: // ./in.cue:10:37 } doesNotDistributeType: (_|_){ // [eval] l: (#list){ } a: (_|_){ // [eval] doesNotDistributeType.a: undefined field: "3": // ./in.cue:13:21 } } stringIndexToList: (_|_){ // [eval] stringIndexToList: undefined field: "": // ./in.cue:16:24 } indexOutOfBounds2: (_|_){ // [eval] indexOutOfBounds2: invalid operand 2 (found int, want list or struct): // ./in.cue:17:20 } booleanIndex: (_|_){ // [eval] booleanIndex: invalid index true (invalid type bool): // ./in.cue:18:20 // ./in.cue:18:23 } indexOutOfBounds3: (_|_){ // [eval] indexOutOfBounds3: index out of range [4] with length 3: // ./in.cue:19:30 } negativeIndex: (_|_){ // [eval] negativeIndex: invalid index -1 (index must be non-negative): // ./in.cue:20:20 // ./in.cue:20:30 } varIndexTooLarge: (_|_){ // [eval] n: (int){ 3 } a: (_|_){ // [eval] varIndexTooLarge.a: index out of range [3] with length 3: // ./in.cue:24:15 } } varNegativeIndex: (_|_){ // [eval] n: (int){ -1 } a: (_|_){ // [eval] varNegativeIndex.a: index n out of range [-1]: // ./in.cue:29:5 // ./in.cue:28:5 // ./in.cue:29:15 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,11 +1,11 @@ Errors: -outOfBoundsDisjunction: invalid list index 1 (out of bounds): +outOfBoundsDisjunction: index out of range [1] with length 0: ./in.cue:7:36 indexDoesNotDistribute: index out of range [0] with length 0: ./in.cue:10:37 -doesNotDistributeType.a: invalid list index "3" (type string): +doesNotDistributeType.a: undefined field: "3": ./in.cue:13:21 -stringIndexToList: invalid list index "" (type string): +stringIndexToList: undefined field: "": ./in.cue:16:24 indexOutOfBounds2: invalid operand 2 (found int, want list or struct): ./in.cue:17:20 @@ -12,7 +12,7 @@ booleanIndex: invalid index true (invalid type bool): ./in.cue:18:20 ./in.cue:18:23 -indexOutOfBounds3: invalid list index 4 (out of bounds): +indexOutOfBounds3: index out of range [4] with length 3: ./in.cue:19:30 negativeIndex: invalid index -1 (index must be non-negative): ./in.cue:20:20 @@ -32,7 +32,7 @@ stringOfNumberIndex: (int){ 3 } indexToDefault: (int){ 0 } outOfBoundsDisjunction: (_|_){ - // [eval] outOfBoundsDisjunction: invalid list index 1 (out of bounds): + // [eval] outOfBoundsDisjunction: index out of range [1] with length 0: // ./in.cue:7:36 } indexDoesNotDistribute: (_|_){ @@ -44,12 +44,12 @@ l: (#list){ } a: (_|_){ - // [eval] doesNotDistributeType.a: invalid list index "3" (type string): + // [eval] doesNotDistributeType.a: undefined field: "3": // ./in.cue:13:21 } } stringIndexToList: (_|_){ - // [eval] stringIndexToList: invalid list index "" (type string): + // [eval] stringIndexToList: undefined field: "": // ./in.cue:16:24 } indexOutOfBounds2: (_|_){ @@ -62,7 +62,7 @@ // ./in.cue:18:23 } indexOutOfBounds3: (_|_){ - // [eval] indexOutOfBounds3: invalid list index 4 (out of bounds): + // [eval] indexOutOfBounds3: index out of range [4] with length 3: // ./in.cue:19:30 } negativeIndex: (_|_){ -- diff/todo/p4 -- Error messages slightly different. -- out/eval -- Errors: outOfBoundsDisjunction: invalid list index 1 (out of bounds): ./in.cue:7:36 indexDoesNotDistribute: index out of range [0] with length 0: ./in.cue:10:37 doesNotDistributeType.a: invalid list index "3" (type string): ./in.cue:13:21 stringIndexToList: invalid list index "" (type string): ./in.cue:16:24 indexOutOfBounds2: invalid operand 2 (found int, want list or struct): ./in.cue:17:20 booleanIndex: invalid index true (invalid type bool): ./in.cue:18:20 ./in.cue:18:23 indexOutOfBounds3: invalid list index 4 (out of bounds): ./in.cue:19:30 negativeIndex: invalid index -1 (index must be non-negative): ./in.cue:20:20 ./in.cue:20:30 varIndexTooLarge.a: index out of range [3] with length 3: ./in.cue:24:15 varNegativeIndex.a: index n out of range [-1]: ./in.cue:29:5 ./in.cue:28:5 ./in.cue:29:15 Result: (_|_){ // [eval] intIndex: (int){ 2 } stringIndex: (string){ "bar" } stringOfNumberIndex: (int){ 3 } indexToDefault: (int){ 0 } outOfBoundsDisjunction: (_|_){ // [eval] outOfBoundsDisjunction: invalid list index 1 (out of bounds): // ./in.cue:7:36 } indexDoesNotDistribute: (_|_){ // [eval] indexDoesNotDistribute: index out of range [0] with length 0: // ./in.cue:10:37 } doesNotDistributeType: (_|_){ // [eval] l: (#list){ } a: (_|_){ // [eval] doesNotDistributeType.a: invalid list index "3" (type string): // ./in.cue:13:21 } } stringIndexToList: (_|_){ // [eval] stringIndexToList: invalid list index "" (type string): // ./in.cue:16:24 } indexOutOfBounds2: (_|_){ // [eval] indexOutOfBounds2: invalid operand 2 (found int, want list or struct): // ./in.cue:17:20 } booleanIndex: (_|_){ // [eval] booleanIndex: invalid index true (invalid type bool): // ./in.cue:18:20 // ./in.cue:18:23 } indexOutOfBounds3: (_|_){ // [eval] indexOutOfBounds3: invalid list index 4 (out of bounds): // ./in.cue:19:30 } negativeIndex: (_|_){ // [eval] negativeIndex: invalid index -1 (index must be non-negative): // ./in.cue:20:20 // ./in.cue:20:30 } varIndexTooLarge: (_|_){ // [eval] n: (int){ 3 } a: (_|_){ // [eval] varIndexTooLarge.a: index out of range [3] with length 3: // ./in.cue:24:15 } } varNegativeIndex: (_|_){ // [eval] n: (int){ -1 } a: (_|_){ // [eval] varNegativeIndex.a: index n out of range [-1]: // ./in.cue:29:5 // ./in.cue:28:5 // ./in.cue:29:15 } } } -- out/compile -- --- in.cue { intIndex: [ 2, ][0] stringIndex: { foo: "bar" }["foo"] stringOfNumberIndex: { "3": 3 }["3"] indexToDefault: (*[ 0, ]|{})[0] outOfBoundsDisjunction: (*[]|{})[1] indexDoesNotDistribute: (*[]|[ 1, ])[0] doesNotDistributeType: { l: [] a: (*〈0;l〉|{ "3": 3 })["3"] } stringIndexToList: [ 2, ][""] indexOutOfBounds2: 2[2] booleanIndex: [][true] indexOutOfBounds3: [ 1, 2, 3, ][4] negativeIndex: [ 1, 2, 3, ][-1] varIndexTooLarge: { n: 3 a: [ 1, 2, 3, ][〈0;n〉] } varNegativeIndex: { n: -1 a: [ 1, 2, 3, ][〈0;n〉] } } cue-lang-cue-db9cc73/cue/testdata/references/labels.txtar000066400000000000000000000161561474664451600235450ustar00rootroot00000000000000-- in.cue -- // Label aliases // direct a: [X=string]: X a: bar: _ // in struct b: [X=string]: {X} b: bar: _ // in structs c: [X=string]: X c: [Y=string]: {{{Y}}} c: bar: _ // in sub field d: [X=string]: name: X d: bar: {} // nested e: [X=string]: [Y=string]: X + Y e: foo: bar: _ patternField: t1: { r=[string]: {b: r | null} a: {r: 0} } patternField: t2: { a: {r: 0} x=[string]: {z: 1, b: x.z} } // Field aliases bar: 3 f1: C="foo\(bar)": { name: "xx" foo: C.name } // nested f1: D="foo\(bar)": E="foo\(bar)baz": { name: "xx" a: D["foo\(bar)baz"].name b: E.name } // Combo c1: C="foo\(bar)": [D=string]: { name: D foo: C.x.name } c1: foo3: x: _ emptyLabel: { "": 1 a: emptyLabel[""] } underscore: a: { // Issue #1454 foo: #Foo foo: "_": "bar" #Foo: [=~""]: string } underscore: c: { foo: "_": "any" foo: [=~""]: string } underscore: d: { bar: "_": "any" #bar: [string]: string bar: #bar } underscore: e: { baz: "_h": "any" #baz: [=~"_"]: string baz: #baz } // TODO: support. Also not yet supported in old implementation. // c10: { // C=[string]: { // name: "x" // foo: C.name // } // } // c2: c1 & { x: _ } invalidPattern: { [=~"BAD)" & =~"x"]: string y: 123 } -- out/eval/stats -- Leaks: 1 Freed: 61 Reused: 56 Allocs: 6 Retain: 4 Unifications: 60 Conjuncts: 109 Disjuncts: 65 -- out/evalalpha -- Errors: invalidPattern: invalid regexp: error parsing regexp: unexpected ): `BAD)`: ./in.cue:96:22 Result: (_|_){ // [eval] a: (struct){ bar: (string){ "bar" } } b: (struct){ bar: (string){ "bar" } } c: (struct){ bar: (string){ "bar" } } d: (struct){ bar: (struct){ name: (string){ "bar" } } } e: (struct){ foo: (struct){ bar: (string){ "foobar" } } } patternField: (struct){ t1: (struct){ a: (struct){ r: (int){ 0 } b: (null){ null } } } t2: (struct){ a: (struct){ r: (int){ 0 } z: (int){ 1 } b: (int){ 1 } } } } bar: (int){ 3 } f1: (struct){ foo3: (struct){ name: (string){ "xx" } foo: (string){ "xx" } foo3baz: (struct){ name: (string){ "xx" } a: (string){ "xx" } b: (string){ "xx" } } } } c1: (struct){ foo3: (struct){ x: (struct){ name: (string){ "x" } foo: (string){ "x" } } } } emptyLabel: (struct){ "": (int){ 1 } a: (int){ 1 } } underscore: (struct){ a: (struct){ foo: (#struct){ "_": (string){ "bar" } } #Foo: (#struct){ } } c: (struct){ foo: (struct){ "_": (string){ "any" } } } d: (struct){ bar: (#struct){ "_": (string){ "any" } } #bar: (#struct){ } } e: (struct){ baz: (#struct){ "_h": (string){ "any" } } #baz: (#struct){ } } } invalidPattern: (_|_){ // [eval] invalidPattern: invalid regexp: error parsing regexp: unexpected ): `BAD)`: // ./in.cue:96:22 y: (int){ 123 } } } -- diff/explanation -- The new evaluator correctly points out that the pattern matching regular expression has invalid syntax. -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,4 +1,10 @@ -(struct){ +Errors: +invalidPattern: invalid regexp: error parsing regexp: unexpected ): `BAD)`: + ./in.cue:96:22 + +Result: +(_|_){ + // [eval] a: (struct){ bar: (string){ "bar" } } @@ -85,7 +91,9 @@ } } } - invalidPattern: (struct){ + invalidPattern: (_|_){ + // [eval] invalidPattern: invalid regexp: error parsing regexp: unexpected ): `BAD)`: + // ./in.cue:96:22 y: (int){ 123 } } } -- out/eval -- (struct){ a: (struct){ bar: (string){ "bar" } } b: (struct){ bar: (string){ "bar" } } c: (struct){ bar: (string){ "bar" } } d: (struct){ bar: (struct){ name: (string){ "bar" } } } e: (struct){ foo: (struct){ bar: (string){ "foobar" } } } patternField: (struct){ t1: (struct){ a: (struct){ r: (int){ 0 } b: (null){ null } } } t2: (struct){ a: (struct){ r: (int){ 0 } z: (int){ 1 } b: (int){ 1 } } } } bar: (int){ 3 } f1: (struct){ foo3: (struct){ name: (string){ "xx" } foo: (string){ "xx" } foo3baz: (struct){ name: (string){ "xx" } a: (string){ "xx" } b: (string){ "xx" } } } } c1: (struct){ foo3: (struct){ x: (struct){ name: (string){ "x" } foo: (string){ "x" } } } } emptyLabel: (struct){ "": (int){ 1 } a: (int){ 1 } } underscore: (struct){ a: (struct){ foo: (#struct){ "_": (string){ "bar" } } #Foo: (#struct){ } } c: (struct){ foo: (struct){ "_": (string){ "any" } } } d: (struct){ bar: (#struct){ "_": (string){ "any" } } #bar: (#struct){ } } e: (struct){ baz: (#struct){ "_h": (string){ "any" } } #baz: (#struct){ } } } invalidPattern: (struct){ y: (int){ 123 } } } -- out/compile -- --- in.cue { a: { [string]: 〈0;-〉 } a: { bar: _ } b: { [string]: { 〈1;-〉 } } b: { bar: _ } c: { [string]: 〈0;-〉 } c: { [string]: { { { 〈3;-〉 } } } } c: { bar: _ } d: { [string]: { name: 〈1;-〉 } } d: { bar: {} } e: { [string]: { [string]: (〈1;-〉 + 〈0;-〉) } } e: { foo: { bar: _ } } patternField: { t1: { [string]: { b: (〈1;(〈0;-〉)〉|null) } a: { r: 0 } } } patternField: { t2: { a: { r: 0 } [string]: { z: 1 b: 〈1;(〈0;-〉)〉.z } } } bar: 3 f1: { "foo\(〈1;bar〉)": { name: "xx" foo: 〈1;("foo\(〈1;bar〉)")〉.name } } f1: { "foo\(〈1;bar〉)": { "foo\(〈2;bar〉)baz": { name: "xx" a: 〈2;("foo\(〈1;bar〉)")〉["foo\(〈3;bar〉)baz"].name b: 〈1;("foo\(〈2;bar〉)baz")〉.name } } } c1: { "foo\(〈1;bar〉)": { [string]: { name: 〈1;-〉 foo: 〈2;("foo\(〈1;bar〉)")〉.x.name } } } c1: { foo3: { x: _ } } emptyLabel: { "": 1 a: 〈1;emptyLabel〉[""] } underscore: { a: { foo: 〈0;#Foo〉 foo: { "_": "bar" } #Foo: { [=~""]: string } } } underscore: { c: { foo: { "_": "any" } foo: { [=~""]: string } } } underscore: { d: { bar: { "_": "any" } #bar: { [string]: string } bar: 〈0;#bar〉 } } underscore: { e: { baz: { "_h": "any" } #baz: { [=~"_"]: string } baz: 〈0;#baz〉 } } invalidPattern: { [(=~"BAD)" & =~"x")]: string y: 123 } } cue-lang-cue-db9cc73/cue/testdata/references/labelstop.txtar000066400000000000000000000006341474664451600242620ustar00rootroot00000000000000TODO: add matching when bulk optional fields are allowed alongside other fields. -- in.cue -- {[X=string]: baz: X} bar: {} -- out/eval/stats -- Leaks: 0 Freed: 3 Reused: 0 Allocs: 3 Retain: 0 Unifications: 3 Conjuncts: 5 Disjuncts: 3 -- out/eval -- (struct){ bar: (struct){ baz: (string){ "bar" } } } -- out/compile -- --- in.cue { { [string]: { baz: 〈1;-〉 } } bar: {} } cue-lang-cue-db9cc73/cue/testdata/references/let.txtar000066400000000000000000000277051474664451600230710ustar00rootroot00000000000000-- in.cue -- import "list" a1list: [{1}] let A1 = a1list a1: 100*A1[0] + A1[0] a2list: [{2}] let A2 = a2list a2: b: 100*A2[0] + A2[0] a3list: [{3}] let A3 = a3list a3: b: c: 100*A3[0] + A3[0] a4list: [{4}] let A4 = a4list a4: [for x in A4 {v: 404}] a5list: [{5}] let A5 = a5list a5: b: [for x in A5 {v: 505}] a6list: [{6}] let A6 = a6list a6: b: c: [for x in A6 {v: 606}] a7list: [{7}] let A7 = a7list a7: {for x in A7 {v: 707}} a8list: [{8}] let A8 = a8list a8: b: {for x in A8 {v: 808}} a9list: [{9}] let A9 = a9list a9: b: c: {for x in A9 {v: 909}} // Issue #609: // When a let value resolved to an incomplete value, it should pass this // incomplete status to the expression in which it used. But 609 reported // a gobbling of this incomplete status. The problem seemed to be not // exclusive to the use of let, though. incompleteLet: { input: [1, 2, 3, 4, 5] last: { min: list.Min(input) max: list.Max(input) } bar: { let mn = last.min let mx = list.max min: mn max: mx } x: { if list.max < 0 { } } } // Let references should also work inside embedded scalars. // Issue #1955 scalarReference: { inScalar: p0: { 5 let x = 6 #b: x } inScalar: p1: { #b: x let x = 6 5 } inList: p0: { let x = { a: 1 } [ x ] } inList: p1: { [ x ] let x = { a: 1 } } } issue1116: { a: { #a: ["a", "b"] let List = #a List[len(List)-1] } b: { let List = #a List[len(List)-1] #a: ["a", "b"] } } -- out/compile -- --- in.cue { a1list: [ { 1 }, ] let A1#1 = 〈0;a1list〉 a1: ((100 * 〈0;let A1#1〉[0]) + 〈0;let A1#1〉[0]) a2list: [ { 2 }, ] let A2#2 = 〈0;a2list〉 a2: { b: ((100 * 〈1;let A2#2〉[0]) + 〈1;let A2#2〉[0]) } a3list: [ { 3 }, ] let A3#3 = 〈0;a3list〉 a3: { b: { c: ((100 * 〈2;let A3#3〉[0]) + 〈2;let A3#3〉[0]) } } a4list: [ { 4 }, ] let A4#4 = 〈0;a4list〉 a4: [ for _, x in 〈1;let A4#4〉 { v: 404 }, ] a5list: [ { 5 }, ] let A5#5 = 〈0;a5list〉 a5: { b: [ for _, x in 〈2;let A5#5〉 { v: 505 }, ] } a6list: [ { 6 }, ] let A6#6 = 〈0;a6list〉 a6: { b: { c: [ for _, x in 〈3;let A6#6〉 { v: 606 }, ] } } a7list: [ { 7 }, ] let A7#7 = 〈0;a7list〉 a7: { for _, x in 〈1;let A7#7〉 { v: 707 } } a8list: [ { 8 }, ] let A8#8 = 〈0;a8list〉 a8: { b: { for _, x in 〈2;let A8#8〉 { v: 808 } } } a9list: [ { 9 }, ] let A9#9 = 〈0;a9list〉 a9: { b: { c: { for _, x in 〈3;let A9#9〉 { v: 909 } } } } incompleteLet: { input: [ 1, 2, 3, 4, 5, ] last: { min: 〈import;list〉.Min(〈1;input〉) max: 〈import;list〉.Max(〈1;input〉) } bar: { let mn#A = 〈1;last〉.min let mx#B = 〈import;list〉.max min: 〈0;let mn#A〉 max: 〈0;let mx#B〉 } x: { if (〈import;list〉.max < 0) {} } } scalarReference: { inScalar: { p0: { 5 let x#C = 6 #b: 〈0;let x#C〉 } } inScalar: { p1: { #b: 〈0;let x#D〉 let x#D = 6 5 } } inList: { p0: { let x#E = { a: 1 } [ 〈1;let x#E〉, ] } } inList: { p1: { [ 〈1;let x#F〉, ] let x#F = { a: 1 } } } } issue1116: { a: { #a: [ "a", "b", ] let List#10 = 〈0;#a〉 〈0;let List#10〉[(len(〈0;let List#10〉) - 1)] } b: { let List#11 = 〈0;#a〉 〈0;let List#11〉[(len(〈0;let List#11〉) - 1)] #a: [ "a", "b", ] } } } -- out/eval/stats -- Leaks: 3 Freed: 112 Reused: 107 Allocs: 8 Retain: 10 Unifications: 115 Conjuncts: 169 Disjuncts: 117 -- out/evalalpha -- (struct){ a1list: (#list){ 0: (int){ 1 } } let A1#1 = ~(a1list) a1: (int){ 101 } a2list: (#list){ 0: (int){ 2 } } let A2#2 = ~(a2list) a2: (struct){ b: (int){ 202 } } a3list: (#list){ 0: (int){ 3 } } let A3#3 = ~(a3list) a3: (struct){ b: (struct){ c: (int){ 303 } } } a4list: (#list){ 0: (int){ 4 } } let A4#4 = ~(a4list) a4: (#list){ 0: (struct){ v: (int){ 404 } } } a5list: (#list){ 0: (int){ 5 } } let A5#5 = ~(a5list) a5: (struct){ b: (#list){ 0: (struct){ v: (int){ 505 } } } } a6list: (#list){ 0: (int){ 6 } } let A6#6 = ~(a6list) a6: (struct){ b: (struct){ c: (#list){ 0: (struct){ v: (int){ 606 } } } } } a7list: (#list){ 0: (int){ 7 } } let A7#7 = ~(a7list) a7: (struct){ v: (int){ 707 } } a8list: (#list){ 0: (int){ 8 } } let A8#8 = ~(a8list) a8: (struct){ b: (struct){ v: (int){ 808 } } } a9list: (#list){ 0: (int){ 9 } } let A9#9 = ~(a9list) a9: (struct){ b: (struct){ c: (struct){ v: (int){ 909 } } } } incompleteLet: (struct){ input: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } 3: (int){ 4 } 4: (int){ 5 } } last: (struct){ min: (int){ 1 } max: (int){ 5 } } bar: (struct){ let mn#A = (int){ 1 } let mx#B = (_|_){ // [incomplete] incompleteLet.bar.mx: undefined field: max: // ./in.cue:54:17 } min: (int){ 1 } max: (_|_){ // [incomplete] incompleteLet.bar.max: undefined field: max: // ./in.cue:54:17 } } x: (_|_){ // [incomplete] incompleteLet.x: undefined field: max: // ./in.cue:61:11 } } scalarReference: (struct){ inScalar: (struct){ p0: (int){ 5 let x#C = (int){ 6 } #b: (int){ 6 } } p1: (int){ 5 #b: (int){ 6 } let x#D = (int){ 6 } } } inList: (struct){ p0: (#list){ let x#E = (struct){ a: (int){ 1 } } 0: (struct){ a: (int){ 1 } } } p1: (#list){ let x#F = (struct){ a: (int){ 1 } } 0: (struct){ a: (int){ 1 } } } } } issue1116: (struct){ a: (string){ "b" #a: (#list){ 0: (string){ "a" } 1: (string){ "b" } } let List#10 = ~(issue1116.a.#a) } b: (string){ "b" let List#11 = ~(issue1116.b.#a) #a: (#list){ 0: (string){ "a" } 1: (string){ "b" } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,16 +2,12 @@ a1list: (#list){ 0: (int){ 1 } } - let A1#1 = (#list){ - 0: (int){ 1 } - } + let A1#1 = ~(a1list) a1: (int){ 101 } a2list: (#list){ 0: (int){ 2 } } - let A2#2 = (#list){ - 0: (int){ 2 } - } + let A2#2 = ~(a2list) a2: (struct){ b: (int){ 202 } } @@ -18,9 +14,7 @@ a3list: (#list){ 0: (int){ 3 } } - let A3#3 = (#list){ - 0: (int){ 3 } - } + let A3#3 = ~(a3list) a3: (struct){ b: (struct){ c: (int){ 303 } @@ -29,9 +23,7 @@ a4list: (#list){ 0: (int){ 4 } } - let A4#4 = (#list){ - 0: (int){ 4 } - } + let A4#4 = ~(a4list) a4: (#list){ 0: (struct){ v: (int){ 404 } @@ -40,9 +32,7 @@ a5list: (#list){ 0: (int){ 5 } } - let A5#5 = (#list){ - 0: (int){ 5 } - } + let A5#5 = ~(a5list) a5: (struct){ b: (#list){ 0: (struct){ @@ -53,9 +43,7 @@ a6list: (#list){ 0: (int){ 6 } } - let A6#6 = (#list){ - 0: (int){ 6 } - } + let A6#6 = ~(a6list) a6: (struct){ b: (struct){ c: (#list){ @@ -68,9 +56,7 @@ a7list: (#list){ 0: (int){ 7 } } - let A7#7 = (#list){ - 0: (int){ 7 } - } + let A7#7 = ~(a7list) a7: (struct){ v: (int){ 707 } } @@ -77,9 +63,7 @@ a8list: (#list){ 0: (int){ 8 } } - let A8#8 = (#list){ - 0: (int){ 8 } - } + let A8#8 = ~(a8list) a8: (struct){ b: (struct){ v: (int){ 808 } @@ -88,9 +72,7 @@ a9list: (#list){ 0: (int){ 9 } } - let A9#9 = (#list){ - 0: (int){ 9 } - } + let A9#9 = ~(a9list) a9: (struct){ b: (struct){ c: (struct){ @@ -166,17 +148,11 @@ 0: (string){ "a" } 1: (string){ "b" } } - let List#10 = (#list){ - 0: (string){ "a" } - 1: (string){ "b" } - } + let List#10 = ~(issue1116.a.#a) } b: (string){ "b" - let List#11 = (_|_){ - // [incomplete] issue1116.b.List: cycle error referencing #a: - // ./in.cue:96:14 - } + let List#11 = ~(issue1116.b.#a) #a: (#list){ 0: (string){ "a" } 1: (string){ "b" } -- out/eval -- (struct){ a1list: (#list){ 0: (int){ 1 } } let A1#1 = (#list){ 0: (int){ 1 } } a1: (int){ 101 } a2list: (#list){ 0: (int){ 2 } } let A2#2 = (#list){ 0: (int){ 2 } } a2: (struct){ b: (int){ 202 } } a3list: (#list){ 0: (int){ 3 } } let A3#3 = (#list){ 0: (int){ 3 } } a3: (struct){ b: (struct){ c: (int){ 303 } } } a4list: (#list){ 0: (int){ 4 } } let A4#4 = (#list){ 0: (int){ 4 } } a4: (#list){ 0: (struct){ v: (int){ 404 } } } a5list: (#list){ 0: (int){ 5 } } let A5#5 = (#list){ 0: (int){ 5 } } a5: (struct){ b: (#list){ 0: (struct){ v: (int){ 505 } } } } a6list: (#list){ 0: (int){ 6 } } let A6#6 = (#list){ 0: (int){ 6 } } a6: (struct){ b: (struct){ c: (#list){ 0: (struct){ v: (int){ 606 } } } } } a7list: (#list){ 0: (int){ 7 } } let A7#7 = (#list){ 0: (int){ 7 } } a7: (struct){ v: (int){ 707 } } a8list: (#list){ 0: (int){ 8 } } let A8#8 = (#list){ 0: (int){ 8 } } a8: (struct){ b: (struct){ v: (int){ 808 } } } a9list: (#list){ 0: (int){ 9 } } let A9#9 = (#list){ 0: (int){ 9 } } a9: (struct){ b: (struct){ c: (struct){ v: (int){ 909 } } } } incompleteLet: (struct){ input: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 3 } 3: (int){ 4 } 4: (int){ 5 } } last: (struct){ min: (int){ 1 } max: (int){ 5 } } bar: (struct){ let mn#A = (int){ 1 } let mx#B = (_|_){ // [incomplete] incompleteLet.bar.mx: undefined field: max: // ./in.cue:54:17 } min: (int){ 1 } max: (_|_){ // [incomplete] incompleteLet.bar.max: undefined field: max: // ./in.cue:54:17 } } x: (_|_){ // [incomplete] incompleteLet.x: undefined field: max: // ./in.cue:61:11 } } scalarReference: (struct){ inScalar: (struct){ p0: (int){ 5 let x#C = (int){ 6 } #b: (int){ 6 } } p1: (int){ 5 #b: (int){ 6 } let x#D = (int){ 6 } } } inList: (struct){ p0: (#list){ let x#E = (struct){ a: (int){ 1 } } 0: (struct){ a: (int){ 1 } } } p1: (#list){ let x#F = (struct){ a: (int){ 1 } } 0: (struct){ a: (int){ 1 } } } } } issue1116: (struct){ a: (string){ "b" #a: (#list){ 0: (string){ "a" } 1: (string){ "b" } } let List#10 = (#list){ 0: (string){ "a" } 1: (string){ "b" } } } b: (string){ "b" let List#11 = (_|_){ // [incomplete] issue1116.b.List: cycle error referencing #a: // ./in.cue:96:14 } #a: (#list){ 0: (string){ "a" } 1: (string){ "b" } } } } } cue-lang-cue-db9cc73/cue/testdata/references/letcycle.txtar000066400000000000000000000045651474664451600241100ustar00rootroot00000000000000-- in.cue -- import "list" cycles: { a: { let A = {c: B} let B = A out: A } b: { let A = {c: B} let B = {A.c} out: A } issue1042: { #FullAdder: { // IN a: bool b: bool c: bool // OUT sum: bool carry: bool } #Add16: { a: [bool] * 16 b: [bool] * 16 out: [bool] * 16 let fulladders = [ for i in list.Range(0, 4, 1) { #FullAdder & {"a": a[i], "b": b[i], c: carries[i]} }, ] let carries = [ false, for i in list.Range(0, 4, 1) {fulladders[i].carry}, ] out: [ for i in list.Range(0, 4, 1) {fulladders[i].sum}, ] } } } -- out/compile -- cycles.a.let[].c.c: cyclic references in let clause or alias: ./in.cue:5:15 cycles.b.let[].c.c: cyclic references in let clause or alias: ./in.cue:11:15 cycles.issue1042.#Add16.let[].for[].c.for[].for[].c: cyclic references in let clause or alias: ./in.cue:34:45 --- in.cue { cycles: { a: { let A#1 = { c: 〈1;let B#2〉 } let B#2 = 〈0;let A#1〉 out: 〈0;let A#1〉 } b: { let A#3 = { c: 〈1;let B#4〉 } let B#4 = { 〈1;let A#3〉.c } out: 〈0;let A#3〉 } issue1042: { #FullAdder: { a: bool b: bool c: bool sum: bool carry: bool } #Add16: { a: ([ bool, ] * 16) b: ([ bool, ] * 16) out: ([ bool, ] * 16) let fulladders#5 = [ for _, i in 〈import;list〉.Range(0, 4, 1) { (〈4;#FullAdder〉 & { a: 〈4;a〉[〈2;i〉] b: 〈4;b〉[〈2;i〉] c: 〈4;let carries#6〉[〈2;i〉] }) }, ] let carries#6 = [ false, for _, i in 〈import;list〉.Range(0, 4, 1) { 〈3;let fulladders#5〉[〈1;i〉].carry }, ] out: [ for _, i in 〈import;list〉.Range(0, 4, 1) { 〈3;let fulladders#5〉[〈1;i〉].sum }, ] } } } } -- out/eval -- cycles.a.let[].c.c: cyclic references in let clause or alias: ./in.cue:5:15 cycles.b.let[].c.c: cyclic references in let clause or alias: ./in.cue:11:15 cycles.issue1042.#Add16.let[].for[].c.for[].for[].c: cyclic references in let clause or alias: ./in.cue:34:45 cue-lang-cue-db9cc73/cue/testdata/references/optional.txtar000066400000000000000000000013741474664451600241240ustar00rootroot00000000000000-- in.cue -- t1: a: { foo?: int b: foo } t2: a: { b: foo foo?: int } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 4 Allocs: 5 Retain: 1 Unifications: 9 Conjuncts: 9 Disjuncts: 10 -- out/eval -- (struct){ t1: (struct){ a: (struct){ foo?: (int){ int } b: (_|_){ // [incomplete] t1.a.b: cannot reference optional field: foo: // ./in.cue:4:5 } } } t2: (struct){ a: (struct){ b: (_|_){ // [incomplete] t2.a.b: cannot reference optional field: foo: // ./in.cue:7:5 } foo?: (int){ int } } } } -- out/compile -- --- in.cue { t1: { a: { foo?: int b: 〈0;foo〉 } } t2: { a: { b: 〈0;foo〉 foo?: int } } } cue-lang-cue-db9cc73/cue/testdata/references/package.txtar000066400000000000000000000012361474664451600236670ustar00rootroot00000000000000-- cue.mod/module.cue -- module: "mod.test" language: version: "v0.9.0" -- in.cue -- package exitcode import ( pkg "foo.com/example" ) a: 1 incomplete: pkg.Settings -- cue.mod/pkg/foo.com/example/example.cue -- package example // An incomplete error in a package is not transferred to a // package that is using it. // // Issue #550 blah: Settings.anyKey Settings: {} -- out/ -- -- out/eval/stats -- Leaks: 1 Freed: 4 Reused: 1 Allocs: 4 Retain: 2 Unifications: 5 Conjuncts: 6 Disjuncts: 6 -- out/eval -- (struct){ a: (int){ 1 } incomplete: (struct){ } } -- out/compile -- --- in.cue { a: 1 incomplete: 〈import;"foo.com/example"〉.Settings } cue-lang-cue-db9cc73/cue/testdata/references/value.txtar000066400000000000000000000021101474664451600234000ustar00rootroot00000000000000-- in.cue -- structShorthand: X={b: 3, c: X.b} // Note that X and Y are subtly different, as they have different bindings: // one binds to the field, the other to the value. In this case, that does not // make a difference. fieldAndValue: X=foo: Y={3, #sum: X + Y} valueCycle: b: X=3 + X // Issue #1003 listValueAlias: X = [1, 2, X[0]] -- out/eval/stats -- Leaks: 0 Freed: 13 Reused: 9 Allocs: 4 Retain: 0 Unifications: 13 Conjuncts: 20 Disjuncts: 13 -- out/eval -- (struct){ structShorthand: (struct){ b: (int){ 3 } c: (int){ 3 } } fieldAndValue: (struct){ foo: (int){ 3 #sum: (int){ 6 } } } valueCycle: (struct){ b: (_|_){ // [cycle] cycle error: // ./in.cue:8:18 } } listValueAlias: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 1 } } } -- out/compile -- --- in.cue { structShorthand: { b: 3 c: 〈1〉.b } fieldAndValue: { foo: { 3 #sum: (〈1;foo〉 + 〈1〉) } } valueCycle: { b: (3 + 〈0〉) } listValueAlias: [ 1, 2, 〈1〉[0], ] } cue-lang-cue-db9cc73/cue/testdata/resolve/000077500000000000000000000000001474664451600205445ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/resolve/000_convert___to_top.txtar000066400000000000000000000006411474664451600255520ustar00rootroot00000000000000#name: convert _ to top #evalPartial -- in.cue -- a: {[_]: _} -- out/def -- a: { ... } -- out/export -- a: {} -- out/yaml -- a: {} -- out/json -- {"a":{}} -- out/legacy-debug -- <0>{a: <1>{...}} -- out/compile -- --- in.cue { a: { [_]: _ } } -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 0 Unifications: 2 Conjuncts: 2 Disjuncts: 2 -- out/eval -- (struct){ a: (struct){ } } cue-lang-cue-db9cc73/cue/testdata/resolve/001.txtar000066400000000000000000000015251474664451600221330ustar00rootroot00000000000000#evalPartial -- in.cue -- a: b.c.d b: c: {d: 3} c: {c: d.d} d: {d: 2} -- out/def -- a: 3 b: { c: { d: 3 } } c: { c: 2 } d: { d: 2 } -- out/export -- a: 3 b: { c: { d: 3 } } c: { c: 2 } d: { d: 2 } -- out/yaml -- a: 3 b: c: d: 3 c: c: 2 d: d: 2 -- out/json -- {"a":3,"b":{"c":{"d":3}},"c":{"c":2},"d":{"d":2}} -- out/legacy-debug -- <0>{a: 3, b: <1>{c: <2>{d: 3}}, c: <3>{c: 2}, d: <4>{d: 2}} -- out/compile -- --- in.cue { a: 〈0;b〉.c.d b: { c: { d: 3 } } c: { c: 〈1;d〉.d } d: { d: 2 } } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 4 Allocs: 5 Retain: 5 Unifications: 9 Conjuncts: 9 Disjuncts: 12 -- out/eval -- (struct){ a: (int){ 3 } b: (struct){ c: (struct){ d: (int){ 3 } } } c: (struct){ c: (int){ 2 } } d: (struct){ d: (int){ 2 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/002.txtar000066400000000000000000000001021474664451600221220ustar00rootroot00000000000000#skip #evalPartial -- out/legacy-debug -- <0>{x: 3, "foo-bar": 3} cue-lang-cue-db9cc73/cue/testdata/resolve/004.txtar000066400000000000000000000011001474664451600221230ustar00rootroot00000000000000#evalPartial -- in.cue -- a: _ b: a a: {d: 1, d: _} b: _ -- out/def -- a: { d: 1 } b: a -- out/export -- a: { d: 1 } b: { d: 1 } -- out/yaml -- a: d: 1 b: d: 1 -- out/json -- {"a":{"d":1},"b":{"d":1}} -- out/legacy-debug -- <0>{a: <1>{d: 1}, b: <2>{d: 1}} -- out/compile -- --- in.cue { a: _ b: 〈0;a〉 a: { d: 1 d: _ } b: _ } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 2 Allocs: 3 Retain: 0 Unifications: 5 Conjuncts: 11 Disjuncts: 5 -- out/eval -- (struct){ a: (struct){ d: (int){ 1 } } b: (struct){ d: (int){ 1 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/005_JSON.txtar000066400000000000000000000013161474664451600227660ustar00rootroot00000000000000#name: JSON #evalPartial -- in.cue -- a="a": 3 b: a o: {"a\nb": 2} // TODO: use $ for root? c: o["a\nb"] -- out/def -- a: 3 b: 3 o: { "a\nb": 2 } c: 2 -- out/export -- a: 3 b: 3 o: { "a\nb": 2 } c: 2 -- out/yaml -- a: 3 b: 3 o: ? |- a b : 2 c: 2 -- out/json -- {"a":3,"b":3,"o":{"a\nb":2},"c":2} -- out/legacy-debug -- <0>{a: 3, b: 3, o: <1>{"a\nb": 2}, c: 2} -- out/compile -- --- in.cue { a: 3 b: 〈0;a〉 o: { "a\nb": 2 } c: 〈0;o〉["a\nb"] } -- out/eval/stats -- Leaks: 0 Freed: 6 Reused: 3 Allocs: 3 Retain: 0 Unifications: 6 Conjuncts: 8 Disjuncts: 6 -- out/eval -- (struct){ a: (int){ 3 } b: (int){ 3 } o: (struct){ "a\nb": (int){ 2 } } c: (int){ 2 } } cue-lang-cue-db9cc73/cue/testdata/resolve/006_arithmetic.txtar000066400000000000000000000021661474664451600243530ustar00rootroot00000000000000#name: arithmetic #evalPartial -- in.cue -- v1: 1.0T / 2.0 v2: 2.0 == 2 n1: 1 v5: 2.0 / n1 v6: 1.0 / 1.0 e2: int & 4.0/2.0 -- out/def -- v1: 5.0000000000e+11 v2: true n1: 1 v5: 2.0 v6: 1. e2: _|_ // conflicting values int and (4.0 / 2.0) (mismatched types int and float) -- out/legacy-debug -- <0>{v1: 5.0000000000e+11, v2: true, n1: 1, v5: 2.0, v6: 1., e2: _|_((int & (4.0 / 2.0)):conflicting values int and (4.0 / 2.0) (mismatched types int and float))} -- out/compile -- --- in.cue { v1: (1000000000000 / 2.0) v2: (2.0 == 2) n1: 1 v5: (2.0 / 〈0;n1〉) v6: (1.0 / 1.0) e2: (int & (4.0 / 2.0)) } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 5 Allocs: 2 Retain: 0 Unifications: 7 Conjuncts: 8 Disjuncts: 7 -- out/eval -- Errors: e2: conflicting values int and 2.0 (mismatched types int and float): ./in.cue:6:5 ./in.cue:6:11 Result: (_|_){ // [eval] v1: (float){ 5.0E+11 } v2: (bool){ true } n1: (int){ 1 } v5: (float){ 2.0 } v6: (float){ 1.0 } e2: (_|_){ // [eval] e2: conflicting values int and 2.0 (mismatched types int and float): // ./in.cue:6:5 // ./in.cue:6:11 } } cue-lang-cue-db9cc73/cue/testdata/resolve/007_inequality.txtar000066400000000000000000000016461474664451600244110ustar00rootroot00000000000000#name: inequality #evalPartial -- in.cue -- a: 1 != 2 b: 1 != null c: true == null d: null != {} e: null == [] f: 0 == 0.0 // types are unified first TODO: make this consistent -- out/def -- a: true b: true c: false d: true e: false f: true -- out/export -- a: true b: true c: false d: true e: false f: true -- out/yaml -- a: true b: true c: false d: true e: false f: true -- out/json -- {"a":true,"b":true,"c":false,"d":true,"e":false,"f":true} -- out/legacy-debug -- <0>{a: true, b: true, c: false, d: true, e: false, f: true} -- out/compile -- --- in.cue { a: (1 != 2) b: (1 != null) c: (true == null) d: (null != {}) e: (null == []) f: (0 == 0.0) } -- out/eval/stats -- Leaks: 2 Freed: 7 Reused: 5 Allocs: 4 Retain: 2 Unifications: 9 Conjuncts: 9 Disjuncts: 9 -- out/eval -- (struct){ a: (bool){ true } b: (bool){ true } c: (bool){ false } d: (bool){ true } e: (bool){ false } f: (bool){ true } } cue-lang-cue-db9cc73/cue/testdata/resolve/008_attributes.txtar000066400000000000000000000016241474664451600244100ustar00rootroot00000000000000#name: attributes #evalPartial -- in.cue -- a: {foo: 1 @foo() @baz(1)} b: {foo: 1 @bar() @foo()} c: a & b e: a & {foo: 1 @foo(other)} -- out/def -- a: { foo: 1 @baz(1) @foo() } b: { foo: 1 @bar() @foo() } c: a & b e: _|_ // conflicting attributes for key "foo" -- out/legacy-debug -- <0>{a: <1>{foo: 1 @baz(1) @foo()}, b: <2>{foo: 1 @bar() @foo()}, c: <3>{foo: 1 @bar() @baz(1) @foo()}, e: _|_((<4>.a & <5>{foo: 1 @foo(other)}):conflicting attributes for key "foo")} -- out/compile -- --- in.cue { a: { foo: 1 } b: { foo: 1 } c: (〈0;a〉 & 〈0;b〉) e: (〈0;a〉 & { foo: 1 }) } -- out/eval/stats -- Leaks: 0 Freed: 9 Reused: 6 Allocs: 3 Retain: 0 Unifications: 9 Conjuncts: 16 Disjuncts: 9 -- out/eval -- (struct){ a: (struct){ foo: (int){ 1 } } b: (struct){ foo: (int){ 1 } } c: (struct){ foo: (int){ 1 } } e: (struct){ foo: (int){ 1 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/009_optional_field_unification.txtar000066400000000000000000000022131474664451600275760ustar00rootroot00000000000000#name: optional field unification #evalPartial -- in.cue -- a: {foo?: string} b: {foo: "foo"} c: a & b d: a & {"foo"?: "bar"} g1: 1 "g\(1)"?: 1 "g\(2)"?: 2 -- out/def -- a: { foo?: string } b: { foo: "foo" } c: a & b d: a & { foo?: "bar" } g1: 1 g2?: 2 -- out/export -- a: {} b: { foo: "foo" } c: { foo: "foo" } d: {} g1: 1 -- out/yaml -- a: {} b: foo: foo c: foo: foo d: {} g1: 1 -- out/json -- {"a":{},"b":{"foo":"foo"},"c":{"foo":"foo"},"d":{},"g1":1} -- out/legacy-debug -- <0>{a: <1>{foo?: string}, b: <2>{foo: "foo"}, c: <3>{foo: "foo"}, d: <4>{foo?: "bar"}, g1: 1, g2?: 2} -- out/compile -- --- in.cue { a: { foo?: string } b: { foo: "foo" } c: (〈0;a〉 & 〈0;b〉) d: (〈0;a〉 & { foo?: "bar" }) g1: 1 "g\(1)"?: 1 "g\(2)"?: 2 } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 19 Disjuncts: 11 -- out/eval -- (struct){ a: (struct){ foo?: (string){ string } } b: (struct){ foo: (string){ "foo" } } c: (struct){ foo: (string){ "foo" } } d: (struct){ foo?: (string){ "bar" } } g1: (int){ 1 } g2?: (int){ 2 } } cue-lang-cue-db9cc73/cue/testdata/resolve/010_optional_field_resolves_to_incomplete.txtar000066400000000000000000000013121474664451600320400ustar00rootroot00000000000000#name: optional field resolves to incomplete #evalPartial -- in.cue -- r: { a?: 3 b: a c: r["a"] } -- out/def -- r: { a?: 3 b: a c: r["a"] } -- out/legacy-debug -- <0>{r: <1>{a?: 3, b: <2>.a, c: <3>.r["a"]}} -- out/compile -- --- in.cue { r: { a?: 3 b: 〈0;a〉 c: 〈1;r〉["a"] } } -- out/eval/stats -- Leaks: 0 Freed: 5 Reused: 2 Allocs: 3 Retain: 0 Unifications: 5 Conjuncts: 5 Disjuncts: 5 -- out/eval -- (struct){ r: (struct){ a?: (int){ 3 } b: (_|_){ // [incomplete] r.b: cannot reference optional field: a: // ./in.cue:3:6 } c: (_|_){ // [incomplete] r.c: cannot reference optional field: a: // ./in.cue:4:8 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/011_bounds.txtar000066400000000000000000000357361474664451600235210ustar00rootroot00000000000000#name: bounds #evalPartial -- in.cue -- i1: >1 & 5 i2: (>=0 & <=10) & 5 i3: !=null & [] i4: !=2 & !=4 s1: >=0 & <=10 & !=1 // no simplification s2: >=0 & <=10 & !=11 // >=0 & <=10 s3: >5 & !=5 // >5 s4: <10 & !=10 // <10 s5: !=2 & !=2 // TODO: could change inequality s6: !=2 & >=2 s7: >=2 & !=2 s8: !=5 & >5 s10: >=0 & <=10 & <12 & >1 // >1 & <=10 s11: >0 & >=0 & <=12 & <12 // >0 & <12 s20: >=10 & <=10 // 10 s22: >5 & <=6 // no simplification s22a: >5 & (<=6 & int) // 6 s22b: (int & >5) & <=6 // 6 s22c: >=5 & (<6 & int) // 5 s22d: (int & >=5) & <6 // 5 s22e: (>=5 & <6) & int // 5 s22f: int & (>=5 & <6) // 5 s23: >0 & <2 // no simplification s23a: (>0 & <2) & int // int & 1 s23b: int & (>0 & <2) // int & 1 s23c: (int & >0) & <2 // int & 1 s23d: >0 & (int & <2) // int & 1 s23e: >0.0 & <2.0 // no simplification s30: >0 & int floats: { [string]: float f1: <10.0 & <=5.0 f2: <=10.0 & <5.0 f3: <1.1 & <=1.1 f4: <=1.1 & <=1.1 f5: >1.1 & >=1.1 f6: >=1.1 & >1.1 f7: >=1.1 & <=1.1 issue1310: >=2.1 & <=1.0 fe2: >2.1 & <=2.1 fe3: float & >2 & <=3 } e1: null & !=null e2: !=null & null e3: >1 & 1 e4: <0 & 0 e5: >1 & <0 e6: >11 & <11 e7: >=11 & <11 e8: >11 & <=11 e9: >"a" & <1 -- out/def -- i1: 5 i2: 5 i3: [] i4: !=2 & !=4 s1: >=0 & <=10 & !=1 s2: >=0 & <=10 s3: >5 s4: <10 s5: !=2 // TODO: could change inequality s6: !=2 s7: !=2 s8: >5 s10: >1 & <=10 s11: >0 & <12 s20: 10 s22: >5 & <=6 s22a: 6 s22b: 6 s22c: 5 s22d: 5 s22e: 5 s22f: 5 s23: >0 & <2 s23a: 1 s23b: 1 s23c: 1 s23d: 1 s23e: >0.0 & <2.0 s30: >0 e1: _|_ // invalid value null (excluded by !=null) e2: _|_ // invalid value null (excluded by !=null) e3: _|_ // invalid value 1 (out of bound >1) e4: _|_ // invalid value 0 (out of bound <0) e5: _|_ // conflicting bounds >1 and <0 e6: _|_ // conflicting bounds >11 and <11 e7: _|_ // conflicting bounds >=11 and <11 e8: _|_ // conflicting bounds >11 and <=11 e9: _|_ // conflicting values >"a" and <1 (mismatched types string and number) -- out/legacy-debug -- <0>{i1: 5, i2: 5, i3: [], i4: (!=2 & !=4), s1: (>=0 & <=10 & !=1), s2: (>=0 & <=10), s3: >5, s4: <10, s5: !=2, s6: (!=2 & >=2), s7: (>=2 & !=2), s8: >5, s10: (<=10 & >1), s11: (>0 & <12), s20: 10, s22: (>5 & <=6), s22a: 6, s22b: 6, s22c: 5, s22d: 5, s22e: 5, s22f: 5, s23: (>0 & <2), s23a: 1, s23b: 1, s23c: 1, s23d: 1, s23e: (>0.0 & <2.0), s30: int & >0, e1: _|_((!=null & null):invalid value null (excluded by !=null)), e2: _|_((!=null & null):invalid value null (excluded by !=null)), e3: _|_((>1 & 1):invalid value 1 (out of bound >1)), e4: _|_((<0 & 0):invalid value 0 (out of bound <0)), e5: _|_(conflicting bounds >1 and <0), e6: _|_(conflicting bounds >11 and <11), e7: _|_(conflicting bounds >=11 and <11), e8: _|_(conflicting bounds >11 and <=11), e9: _|_((>"a" & <1):conflicting values >"a" and <1 (mismatched types string and number))} -- out/compile -- --- in.cue { i1: (>1 & 5) i2: ((>=0 & <=10) & 5) i3: (!=null & []) i4: (!=2 & !=4) s1: ((>=0 & <=10) & !=1) s2: ((>=0 & <=10) & !=11) s3: (>5 & !=5) s4: (<10 & !=10) s5: (!=2 & !=2) s6: (!=2 & >=2) s7: (>=2 & !=2) s8: (!=5 & >5) s10: (((>=0 & <=10) & <12) & >1) s11: (((>0 & >=0) & <=12) & <12) s20: (>=10 & <=10) s22: (>5 & <=6) s22a: (>5 & (<=6 & int)) s22b: ((int & >5) & <=6) s22c: (>=5 & (<6 & int)) s22d: ((int & >=5) & <6) s22e: ((>=5 & <6) & int) s22f: (int & (>=5 & <6)) s23: (>0 & <2) s23a: ((>0 & <2) & int) s23b: (int & (>0 & <2)) s23c: ((int & >0) & <2) s23d: (>0 & (int & <2)) s23e: (>0.0 & <2.0) s30: (>0 & int) floats: { [string]: float f1: (<10.0 & <=5.0) f2: (<=10.0 & <5.0) f3: (<1.1 & <=1.1) f4: (<=1.1 & <=1.1) f5: (>1.1 & >=1.1) f6: (>=1.1 & >1.1) f7: (>=1.1 & <=1.1) issue1310: (>=2.1 & <=1.0) fe2: (>2.1 & <=2.1) fe3: ((float & >2) & <=3) } e1: (null & !=null) e2: (!=null & null) e3: (>1 & 1) e4: (<0 & 0) e5: (>1 & <0) e6: (>11 & <11) e7: (>=11 & <11) e8: (>11 & <=11) e9: (>"a" & <1) } -- out/eval/stats -- Leaks: 0 Freed: 50 Reused: 47 Allocs: 3 Retain: 0 Unifications: 50 Conjuncts: 126 Disjuncts: 50 -- out/evalalpha -- Errors: e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): ./in.cue:56:5 ./in.cue:56:12 e2: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): ./in.cue:57:5 ./in.cue:57:14 e9: conflicting values >"a" and <1 (mismatched types string and number): ./in.cue:64:5 ./in.cue:64:12 floats.issue1310: incompatible number bounds <=1.0 and >=2.1: ./in.cue:50:21 ./in.cue:50:13 floats.fe2: incompatible number bounds <=2.1 and >2.1: ./in.cue:51:20 ./in.cue:51:13 e3: invalid value 1 (out of bound >1): ./in.cue:58:5 ./in.cue:58:10 e4: invalid value 0 (out of bound <0): ./in.cue:59:5 ./in.cue:59:10 e5: incompatible number bounds <0 and >1: ./in.cue:60:10 ./in.cue:60:5 e6: incompatible number bounds <11 and >11: ./in.cue:61:11 ./in.cue:61:5 e7: incompatible number bounds <11 and >=11: ./in.cue:62:12 ./in.cue:62:5 e8: incompatible number bounds <=11 and >11: ./in.cue:63:11 ./in.cue:63:5 Result: (_|_){ // [eval] i1: (int){ 5 } i2: (int){ 5 } i3: (#list){ } i4: (number){ &(!=2, !=4) } s1: (number){ &(>=0, <=10, !=1) } s2: (number){ &(>=0, <=10) } s3: (number){ >5 } s4: (number){ <10 } s5: (number){ !=2 } s6: (number){ &(>=2, !=2) } s7: (number){ &(>=2, !=2) } s8: (number){ >5 } s10: (number){ &(>1, <=10) } s11: (number){ &(>0, <12) } s20: (number){ 10 } s22: (number){ &(>5, <=6) } s22a: (int){ 6 } s22b: (int){ 6 } s22c: (int){ 5 } s22d: (int){ 5 } s22e: (int){ 5 } s22f: (int){ 5 } s23: (number){ &(>0, <2) } s23a: (int){ 1 } s23b: (int){ 1 } s23c: (int){ 1 } s23d: (int){ 1 } s23e: (number){ &(>0.0, <2.0) } s30: (int){ &(>0, int) } floats: (_|_){ // [eval] f1: (float){ &(<=5.0, float) } f2: (float){ &(<5.0, float) } f3: (float){ &(<1.1, float) } f4: (float){ &(<=1.1, float) } f5: (float){ &(>1.1, float) } f6: (float){ &(>1.1, float) } f7: (float){ 1.1 } issue1310: (_|_){ // [eval] floats.issue1310: incompatible number bounds <=1.0 and >=2.1: // ./in.cue:50:21 // ./in.cue:50:13 } fe2: (_|_){ // [eval] floats.fe2: incompatible number bounds <=2.1 and >2.1: // ./in.cue:51:20 // ./in.cue:51:13 } fe3: (float){ &(>2, <=3, float) } } e1: (_|_){ // [eval] e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): // ./in.cue:56:5 // ./in.cue:56:12 } e2: (_|_){ // [eval] e2: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): // ./in.cue:57:5 // ./in.cue:57:14 } e3: (_|_){ // [eval] e3: invalid value 1 (out of bound >1): // ./in.cue:58:5 // ./in.cue:58:10 } e4: (_|_){ // [eval] e4: invalid value 0 (out of bound <0): // ./in.cue:59:5 // ./in.cue:59:10 } e5: (_|_){ // [eval] e5: incompatible number bounds <0 and >1: // ./in.cue:60:10 // ./in.cue:60:5 } e6: (_|_){ // [eval] e6: incompatible number bounds <11 and >11: // ./in.cue:61:11 // ./in.cue:61:5 } e7: (_|_){ // [eval] e7: incompatible number bounds <11 and >=11: // ./in.cue:62:12 // ./in.cue:62:5 } e8: (_|_){ // [eval] e8: incompatible number bounds <=11 and >11: // ./in.cue:63:11 // ./in.cue:63:5 } e9: (_|_){ // [eval] e9: conflicting values >"a" and <1 (mismatched types string and number): // ./in.cue:64:5 // ./in.cue:64:12 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -2,30 +2,18 @@ e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): ./in.cue:56:5 ./in.cue:56:12 -e2: conflicting values !=null and null (mismatched types (bool|string|bytes|func|list|struct|number) and null): +e2: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): ./in.cue:57:5 ./in.cue:57:14 -e5: incompatible number bounds <0 and >1: - ./in.cue:60:5 - ./in.cue:60:10 -e6: incompatible number bounds <11 and >11: - ./in.cue:61:5 - ./in.cue:61:11 -e7: incompatible number bounds <11 and >=11: - ./in.cue:62:5 - ./in.cue:62:12 -e8: incompatible number bounds <=11 and >11: - ./in.cue:63:5 - ./in.cue:63:11 e9: conflicting values >"a" and <1 (mismatched types string and number): ./in.cue:64:5 ./in.cue:64:12 -floats.fe2: incompatible number bounds <=2.1 and >2.1: - ./in.cue:51:13 - ./in.cue:51:20 floats.issue1310: incompatible number bounds <=1.0 and >=2.1: - ./in.cue:50:13 ./in.cue:50:21 + ./in.cue:50:13 +floats.fe2: incompatible number bounds <=2.1 and >2.1: + ./in.cue:51:20 + ./in.cue:51:13 e3: invalid value 1 (out of bound >1): ./in.cue:58:5 ./in.cue:58:10 @@ -32,6 +20,18 @@ e4: invalid value 0 (out of bound <0): ./in.cue:59:5 ./in.cue:59:10 +e5: incompatible number bounds <0 and >1: + ./in.cue:60:10 + ./in.cue:60:5 +e6: incompatible number bounds <11 and >11: + ./in.cue:61:11 + ./in.cue:61:5 +e7: incompatible number bounds <11 and >=11: + ./in.cue:62:12 + ./in.cue:62:5 +e8: incompatible number bounds <=11 and >11: + ./in.cue:63:11 + ./in.cue:63:5 Result: (_|_){ @@ -74,16 +74,16 @@ f4: (float){ &(<=1.1, float) } f5: (float){ &(>1.1, float) } f6: (float){ &(>1.1, float) } - f7: (number){ 1.1 } + f7: (float){ 1.1 } issue1310: (_|_){ // [eval] floats.issue1310: incompatible number bounds <=1.0 and >=2.1: - // ./in.cue:50:13 // ./in.cue:50:21 + // ./in.cue:50:13 } fe2: (_|_){ // [eval] floats.fe2: incompatible number bounds <=2.1 and >2.1: - // ./in.cue:51:13 // ./in.cue:51:20 + // ./in.cue:51:13 } fe3: (float){ &(>2, <=3, float) } } @@ -93,7 +93,7 @@ // ./in.cue:56:12 } e2: (_|_){ - // [eval] e2: conflicting values !=null and null (mismatched types (bool|string|bytes|func|list|struct|number) and null): + // [eval] e2: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): // ./in.cue:57:5 // ./in.cue:57:14 } @@ -109,23 +109,23 @@ } e5: (_|_){ // [eval] e5: incompatible number bounds <0 and >1: - // ./in.cue:60:5 // ./in.cue:60:10 + // ./in.cue:60:5 } e6: (_|_){ // [eval] e6: incompatible number bounds <11 and >11: - // ./in.cue:61:5 // ./in.cue:61:11 + // ./in.cue:61:5 } e7: (_|_){ // [eval] e7: incompatible number bounds <11 and >=11: - // ./in.cue:62:5 // ./in.cue:62:12 + // ./in.cue:62:5 } e8: (_|_){ // [eval] e8: incompatible number bounds <=11 and >11: - // ./in.cue:63:5 // ./in.cue:63:11 + // ./in.cue:63:5 } e9: (_|_){ // [eval] e9: conflicting values >"a" and <1 (mismatched types string and number): -- diff/todo/p3 -- Reordering -- diff/explanation -- f7 changed from number to float. This is a bug fix. -- out/eval -- Errors: e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): ./in.cue:56:5 ./in.cue:56:12 e2: conflicting values !=null and null (mismatched types (bool|string|bytes|func|list|struct|number) and null): ./in.cue:57:5 ./in.cue:57:14 e5: incompatible number bounds <0 and >1: ./in.cue:60:5 ./in.cue:60:10 e6: incompatible number bounds <11 and >11: ./in.cue:61:5 ./in.cue:61:11 e7: incompatible number bounds <11 and >=11: ./in.cue:62:5 ./in.cue:62:12 e8: incompatible number bounds <=11 and >11: ./in.cue:63:5 ./in.cue:63:11 e9: conflicting values >"a" and <1 (mismatched types string and number): ./in.cue:64:5 ./in.cue:64:12 floats.fe2: incompatible number bounds <=2.1 and >2.1: ./in.cue:51:13 ./in.cue:51:20 floats.issue1310: incompatible number bounds <=1.0 and >=2.1: ./in.cue:50:13 ./in.cue:50:21 e3: invalid value 1 (out of bound >1): ./in.cue:58:5 ./in.cue:58:10 e4: invalid value 0 (out of bound <0): ./in.cue:59:5 ./in.cue:59:10 Result: (_|_){ // [eval] i1: (int){ 5 } i2: (int){ 5 } i3: (#list){ } i4: (number){ &(!=2, !=4) } s1: (number){ &(>=0, <=10, !=1) } s2: (number){ &(>=0, <=10) } s3: (number){ >5 } s4: (number){ <10 } s5: (number){ !=2 } s6: (number){ &(>=2, !=2) } s7: (number){ &(>=2, !=2) } s8: (number){ >5 } s10: (number){ &(>1, <=10) } s11: (number){ &(>0, <12) } s20: (number){ 10 } s22: (number){ &(>5, <=6) } s22a: (int){ 6 } s22b: (int){ 6 } s22c: (int){ 5 } s22d: (int){ 5 } s22e: (int){ 5 } s22f: (int){ 5 } s23: (number){ &(>0, <2) } s23a: (int){ 1 } s23b: (int){ 1 } s23c: (int){ 1 } s23d: (int){ 1 } s23e: (number){ &(>0.0, <2.0) } s30: (int){ &(>0, int) } floats: (_|_){ // [eval] f1: (float){ &(<=5.0, float) } f2: (float){ &(<5.0, float) } f3: (float){ &(<1.1, float) } f4: (float){ &(<=1.1, float) } f5: (float){ &(>1.1, float) } f6: (float){ &(>1.1, float) } f7: (number){ 1.1 } issue1310: (_|_){ // [eval] floats.issue1310: incompatible number bounds <=1.0 and >=2.1: // ./in.cue:50:13 // ./in.cue:50:21 } fe2: (_|_){ // [eval] floats.fe2: incompatible number bounds <=2.1 and >2.1: // ./in.cue:51:13 // ./in.cue:51:20 } fe3: (float){ &(>2, <=3, float) } } e1: (_|_){ // [eval] e1: conflicting values null and !=null (mismatched types null and (bool|string|bytes|func|list|struct|number)): // ./in.cue:56:5 // ./in.cue:56:12 } e2: (_|_){ // [eval] e2: conflicting values !=null and null (mismatched types (bool|string|bytes|func|list|struct|number) and null): // ./in.cue:57:5 // ./in.cue:57:14 } e3: (_|_){ // [eval] e3: invalid value 1 (out of bound >1): // ./in.cue:58:5 // ./in.cue:58:10 } e4: (_|_){ // [eval] e4: invalid value 0 (out of bound <0): // ./in.cue:59:5 // ./in.cue:59:10 } e5: (_|_){ // [eval] e5: incompatible number bounds <0 and >1: // ./in.cue:60:5 // ./in.cue:60:10 } e6: (_|_){ // [eval] e6: incompatible number bounds <11 and >11: // ./in.cue:61:5 // ./in.cue:61:11 } e7: (_|_){ // [eval] e7: incompatible number bounds <11 and >=11: // ./in.cue:62:5 // ./in.cue:62:12 } e8: (_|_){ // [eval] e8: incompatible number bounds <=11 and >11: // ./in.cue:63:5 // ./in.cue:63:11 } e9: (_|_){ // [eval] e9: conflicting values >"a" and <1 (mismatched types string and number): // ./in.cue:64:5 // ./in.cue:64:12 } } cue-lang-cue-db9cc73/cue/testdata/resolve/012_bound_conversions.txtar000066400000000000000000000067371474664451600257660ustar00rootroot00000000000000#name: bound conversions #evalPartial -- in.cue -- r0: int & >0.1 & <=1.9 r1: int & >0.1 & <1.9 r2: int & >=0.1 & <1.9 r3: int & >=-1.9 & <=-0.1 r4: int & >-1.9 & <=-0.1 r5: >=1.1 & <=1.1 r6: r5 & 1.1 c1: (1.2 & >1.3) & <2 c2: 1.2 & (>1.3 & <2) c3: 1.2 & (>=1 & <2) c4: 1.2 & (>=1 & <2 & int) -- out/def -- r0: 1 r1: 1 r2: 1 r3: -1 r4: -1 r5: 1.1 r6: 1.1 c1: _|_ // invalid value 1.2 (out of bound >1.3) c2: _|_ // invalid value 1.2 (out of bound >1.3) c3: 1.2 c4: _|_ // conflicting values 1.2 and ((>=1 & <2) & int) (mismatched types float and int) -- out/legacy-debug -- <0>{r0: 1, r1: 1, r2: 1, r3: -1, r4: -1, r5: 1.1, r6: 1.1, c1: _|_((>1.3 & 1.2):invalid value 1.2 (out of bound >1.3)), c2: _|_((>1.3 & 1.2):invalid value 1.2 (out of bound >1.3)), c3: 1.2, c4: _|_((1.2 & ((>=1 & <2) & int)):conflicting values 1.2 and ((>=1 & <2) & int) (mismatched types float and int))} -- out/compile -- --- in.cue { r0: ((int & >0.1) & <=1.9) r1: ((int & >0.1) & <1.9) r2: ((int & >=0.1) & <1.9) r3: ((int & >=-1.9) & <=-0.1) r4: ((int & >-1.9) & <=-0.1) r5: (>=1.1 & <=1.1) r6: (〈0;r5〉 & 1.1) c1: ((1.2 & >1.3) & <2) c2: (1.2 & (>1.3 & <2)) c3: (1.2 & (>=1 & <2)) c4: (1.2 & ((>=1 & <2) & int)) } -- out/eval/stats -- Leaks: 0 Freed: 12 Reused: 10 Allocs: 2 Retain: 0 Unifications: 12 Conjuncts: 35 Disjuncts: 12 -- out/evalalpha -- Errors: c4: conflicting values 1.2 and int (mismatched types float and int): ./in.cue:14:5 ./in.cue:14:23 c1: invalid value 1.2 (out of bound >1.3): ./in.cue:10:12 ./in.cue:10:6 c2: invalid value 1.2 (out of bound >1.3): ./in.cue:11:12 ./in.cue:11:5 Result: (_|_){ // [eval] r0: (int){ 1 } r1: (int){ 1 } r2: (int){ 1 } r3: (int){ -1 } r4: (int){ -1 } r5: (number){ 1.1 } r6: (float){ 1.1 } c1: (_|_){ // [eval] c1: invalid value 1.2 (out of bound >1.3): // ./in.cue:10:12 // ./in.cue:10:6 } c2: (_|_){ // [eval] c2: invalid value 1.2 (out of bound >1.3): // ./in.cue:11:12 // ./in.cue:11:5 } c3: (float){ 1.2 } c4: (_|_){ // [eval] c4: conflicting values 1.2 and int (mismatched types float and int): // ./in.cue:14:5 // ./in.cue:14:23 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -18,7 +18,7 @@ r3: (int){ -1 } r4: (int){ -1 } r5: (number){ 1.1 } - r6: (number){ 1.1 } + r6: (float){ 1.1 } c1: (_|_){ // [eval] c1: invalid value 1.2 (out of bound >1.3): // ./in.cue:10:12 -- diff/todo/p3 -- Seems like a correct fix, but investigate. This is independent from the fact that we probably want to relax the type of float literals to number. -- out/eval -- Errors: c4: conflicting values 1.2 and int (mismatched types float and int): ./in.cue:14:5 ./in.cue:14:23 c1: invalid value 1.2 (out of bound >1.3): ./in.cue:10:12 ./in.cue:10:6 c2: invalid value 1.2 (out of bound >1.3): ./in.cue:11:12 ./in.cue:11:5 Result: (_|_){ // [eval] r0: (int){ 1 } r1: (int){ 1 } r2: (int){ 1 } r3: (int){ -1 } r4: (int){ -1 } r5: (number){ 1.1 } r6: (number){ 1.1 } c1: (_|_){ // [eval] c1: invalid value 1.2 (out of bound >1.3): // ./in.cue:10:12 // ./in.cue:10:6 } c2: (_|_){ // [eval] c2: invalid value 1.2 (out of bound >1.3): // ./in.cue:11:12 // ./in.cue:11:5 } c3: (float){ 1.2 } c4: (_|_){ // [eval] c4: conflicting values 1.2 and int (mismatched types float and int): // ./in.cue:14:5 // ./in.cue:14:23 } } cue-lang-cue-db9cc73/cue/testdata/resolve/013_custom_validators.txtar000066400000000000000000000023041474664451600257540ustar00rootroot00000000000000#name: custom validators #evalPartial -- in.cue -- import "strings" a: strings.ContainsAny("ab") a: "after" b: strings.ContainsAny("c") b: "dog" c: strings.ContainsAny("d") & strings.ContainsAny("g") c: "dog" -- out/def -- a: "after" b: _|_ // invalid value "dog" (does not satisfy strings.ContainsAny("c")) c: "dog" -- out/legacy-debug -- <0>{a: "after", b: _|_(strings.ContainsAny ("c"):invalid value "dog" (does not satisfy strings.ContainsAny("c"))), c: "dog"} -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 2 Allocs: 2 Retain: 0 Unifications: 4 Conjuncts: 8 Disjuncts: 4 -- out/eval -- Errors: b: invalid value "dog" (does not satisfy strings.ContainsAny("c")): ./in.cue:6:4 ./in.cue:6:24 ./in.cue:7:4 Result: (_|_){ // [eval] a: (string){ "after" } b: (_|_){ // [eval] b: invalid value "dog" (does not satisfy strings.ContainsAny("c")): // ./in.cue:6:4 // ./in.cue:6:24 // ./in.cue:7:4 } c: (string){ "dog" } } -- out/compile -- --- in.cue { a: 〈import;strings〉.ContainsAny("ab") a: "after" b: 〈import;strings〉.ContainsAny("c") b: "dog" c: (〈import;strings〉.ContainsAny("d") & 〈import;strings〉.ContainsAny("g")) c: "dog" } cue-lang-cue-db9cc73/cue/testdata/resolve/014_null_coalescing.txtar000066400000000000000000000011151474664451600253530ustar00rootroot00000000000000#name: null coalescing #evalPartial -- in.cue -- a: null b: a.x | "b" c: a["x"] | "c" -- out/def -- a: null b: "b" c: "c" -- out/export -- a: null b: "b" c: "c" -- out/yaml -- a: null b: b c: c -- out/json -- {"a":null,"b":"b","c":"c"} -- out/legacy-debug -- <0>{a: null, b: "b", c: "c"} -- out/compile -- --- in.cue { a: null b: (〈0;a〉.x|"b") c: (〈0;a〉["x"]|"c") } -- out/eval/stats -- Leaks: 0 Freed: 8 Reused: 5 Allocs: 3 Retain: 0 Unifications: 4 Conjuncts: 8 Disjuncts: 8 -- out/eval -- (struct){ a: (null){ null } b: (string){ "b" } c: (string){ "c" } } cue-lang-cue-db9cc73/cue/testdata/resolve/016_index.txtar000066400000000000000000000171211474664451600233270ustar00rootroot00000000000000#name: index #evalPartial -- in.cue -- a: [2][0] b: {foo: "bar"}["foo"] c: (*l | {"3": 3})["3"] d: (*[] | [1])[0] l: [] e1: [2][""] e2: 2[2] e3: [][true] e4: [1, 2, 3][3] e5: [1, 2, 3][-1] e6: (*[] | {})[1] e7: [1, 2, 3][3] e8: [1, 2, 3][-1] e9: (*[] | {})[1] def: { a: 1 #b: 3 } e7: def["b"] -- out/def -- a: 2 b: "bar" c: _|_ // invalid list index "3" (type string) l: [] d: _|_ // index 0 out of bounds e1: _|_ // invalid list index "" (type string) e2: _|_ // invalid operation: 2[2] (type int does not support indexing) e3: _|_ // invalid list index true (type bool) e4: _|_ // index 3 out of bounds e5: _|_ // invalid list index -1 (index must be non-negative) e6: _|_ // index 1 out of bounds def: { a: 1 #b: 3 } e7: def["b"] -- out/legacy-debug -- <0>{a: 2, b: "bar", c: _|_("3":invalid list index "3" (type string)), l: [], d: _|_([]:index 0 out of bounds), e1: _|_("":invalid list index "" (type string)), e2: _|_(2:invalid operation: 2[2] (type int does not support indexing)), e3: _|_(true:invalid list index true (type bool)), e4: _|_([1,2,3]:index 3 out of bounds), e5: _|_(-1:invalid list index -1 (index must be non-negative)), e6: _|_([]:index 1 out of bounds), def: <1>{a: 1, #b: 3}, e7: <2>.def["b"]} -- out/compile -- --- in.cue { a: [ 2, ][0] b: { foo: "bar" }["foo"] c: (*〈0;l〉|{ "3": 3 })["3"] d: (*[]|[ 1, ])[0] l: [] e1: [ 2, ][""] e2: 2[2] e3: [][true] e4: [ 1, 2, 3, ][3] e5: [ 1, 2, 3, ][-1] e6: (*[]|{})[1] e7: [ 1, 2, 3, ][3] e8: [ 1, 2, 3, ][-1] e9: (*[]|{})[1] def: { a: 1 #b: 3 } e7: 〈0;def〉["b"] } -- out/eval/stats -- Leaks: 10 Freed: 32 Reused: 26 Allocs: 16 Retain: 12 Unifications: 34 Conjuncts: 44 Disjuncts: 42 -- out/evalalpha -- Errors: c: undefined field: "3": ./in.cue:3:20 d: index out of range [0] with length 0: ./in.cue:4:16 e1: undefined field: "": ./in.cue:6:9 e2: invalid operand 2 (found int, want list or struct): ./in.cue:7:5 e3: invalid index true (invalid type bool): ./in.cue:8:5 ./in.cue:8:8 e4: index out of range [3] with length 3: ./in.cue:9:15 e5: invalid index -1 (index must be non-negative): ./in.cue:10:5 ./in.cue:10:15 e6: index out of range [1] with length 0: ./in.cue:11:16 e7: index out of range [3] with length 3: ./in.cue:12:15 e8: invalid index -1 (index must be non-negative): ./in.cue:13:5 ./in.cue:13:15 e9: index out of range [1] with length 0: ./in.cue:14:16 Result: (_|_){ // [eval] a: (int){ 2 } b: (string){ "bar" } c: (_|_){ // [eval] c: undefined field: "3": // ./in.cue:3:20 } d: (_|_){ // [eval] d: index out of range [0] with length 0: // ./in.cue:4:16 } l: (#list){ } e1: (_|_){ // [eval] e1: undefined field: "": // ./in.cue:6:9 } e2: (_|_){ // [eval] e2: invalid operand 2 (found int, want list or struct): // ./in.cue:7:5 } e3: (_|_){ // [eval] e3: invalid index true (invalid type bool): // ./in.cue:8:5 // ./in.cue:8:8 } e4: (_|_){ // [eval] e4: index out of range [3] with length 3: // ./in.cue:9:15 } e5: (_|_){ // [eval] e5: invalid index -1 (index must be non-negative): // ./in.cue:10:5 // ./in.cue:10:15 } e6: (_|_){ // [eval] e6: index out of range [1] with length 0: // ./in.cue:11:16 } e7: (_|_){ // [eval] e7: index out of range [3] with length 3: // ./in.cue:12:15 } e8: (_|_){ // [eval] e8: invalid index -1 (index must be non-negative): // ./in.cue:13:5 // ./in.cue:13:15 } e9: (_|_){ // [eval] e9: index out of range [1] with length 0: // ./in.cue:14:16 } def: (struct){ a: (int){ 1 } #b: (int){ 3 } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,9 +1,9 @@ Errors: -c: invalid list index "3" (type string): +c: undefined field: "3": ./in.cue:3:20 d: index out of range [0] with length 0: ./in.cue:4:16 -e1: invalid list index "" (type string): +e1: undefined field: "": ./in.cue:6:9 e2: invalid operand 2 (found int, want list or struct): ./in.cue:7:5 @@ -15,7 +15,7 @@ e5: invalid index -1 (index must be non-negative): ./in.cue:10:5 ./in.cue:10:15 -e6: invalid list index 1 (out of bounds): +e6: index out of range [1] with length 0: ./in.cue:11:16 e7: index out of range [3] with length 3: ./in.cue:12:15 @@ -22,7 +22,7 @@ e8: invalid index -1 (index must be non-negative): ./in.cue:13:5 ./in.cue:13:15 -e9: invalid list index 1 (out of bounds): +e9: index out of range [1] with length 0: ./in.cue:14:16 Result: @@ -31,7 +31,7 @@ a: (int){ 2 } b: (string){ "bar" } c: (_|_){ - // [eval] c: invalid list index "3" (type string): + // [eval] c: undefined field: "3": // ./in.cue:3:20 } d: (_|_){ @@ -41,7 +41,7 @@ l: (#list){ } e1: (_|_){ - // [eval] e1: invalid list index "" (type string): + // [eval] e1: undefined field: "": // ./in.cue:6:9 } e2: (_|_){ @@ -63,7 +63,7 @@ // ./in.cue:10:15 } e6: (_|_){ - // [eval] e6: invalid list index 1 (out of bounds): + // [eval] e6: index out of range [1] with length 0: // ./in.cue:11:16 } e7: (_|_){ @@ -76,7 +76,7 @@ // ./in.cue:13:15 } e9: (_|_){ - // [eval] e9: invalid list index 1 (out of bounds): + // [eval] e9: index out of range [1] with length 0: // ./in.cue:14:16 } def: (struct){ -- diff/todo/p3 -- Error messages slightly different. -- out/eval -- Errors: c: invalid list index "3" (type string): ./in.cue:3:20 d: index out of range [0] with length 0: ./in.cue:4:16 e1: invalid list index "" (type string): ./in.cue:6:9 e2: invalid operand 2 (found int, want list or struct): ./in.cue:7:5 e3: invalid index true (invalid type bool): ./in.cue:8:5 ./in.cue:8:8 e4: index out of range [3] with length 3: ./in.cue:9:15 e5: invalid index -1 (index must be non-negative): ./in.cue:10:5 ./in.cue:10:15 e6: invalid list index 1 (out of bounds): ./in.cue:11:16 e7: index out of range [3] with length 3: ./in.cue:12:15 e8: invalid index -1 (index must be non-negative): ./in.cue:13:5 ./in.cue:13:15 e9: invalid list index 1 (out of bounds): ./in.cue:14:16 Result: (_|_){ // [eval] a: (int){ 2 } b: (string){ "bar" } c: (_|_){ // [eval] c: invalid list index "3" (type string): // ./in.cue:3:20 } d: (_|_){ // [eval] d: index out of range [0] with length 0: // ./in.cue:4:16 } l: (#list){ } e1: (_|_){ // [eval] e1: invalid list index "" (type string): // ./in.cue:6:9 } e2: (_|_){ // [eval] e2: invalid operand 2 (found int, want list or struct): // ./in.cue:7:5 } e3: (_|_){ // [eval] e3: invalid index true (invalid type bool): // ./in.cue:8:5 // ./in.cue:8:8 } e4: (_|_){ // [eval] e4: index out of range [3] with length 3: // ./in.cue:9:15 } e5: (_|_){ // [eval] e5: invalid index -1 (index must be non-negative): // ./in.cue:10:5 // ./in.cue:10:15 } e6: (_|_){ // [eval] e6: invalid list index 1 (out of bounds): // ./in.cue:11:16 } e7: (_|_){ // [eval] e7: index out of range [3] with length 3: // ./in.cue:12:15 } e8: (_|_){ // [eval] e8: invalid index -1 (index must be non-negative): // ./in.cue:13:5 // ./in.cue:13:15 } e9: (_|_){ // [eval] e9: invalid list index 1 (out of bounds): // ./in.cue:14:16 } def: (struct){ a: (int){ 1 } #b: (int){ 3 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/017_disjunctions_of_lists.txtar000066400000000000000000000015741474664451600266440ustar00rootroot00000000000000#name: disjunctions of lists #evalPartial -- in.cue -- l: [ int, int] | [ string, string] l1: ["a", "b"] l2: l & ["c", "d"] -- out/def -- l: [int, int] | [string, string] l1: ["a", "b"] l2: ["c", "d"] -- out/legacy-debug -- <0>{l: ([int,int] | [string,string]), l1: ["a","b"], l2: ["c","d"]} -- out/compile -- --- in.cue { l: ([ int, int, ]|[ string, string, ]) l1: [ "a", "b", ] l2: (〈0;l〉 & [ "c", "d", ]) } -- out/eval/stats -- Leaks: 0 Freed: 18 Reused: 13 Allocs: 5 Retain: 0 Unifications: 14 Conjuncts: 24 Disjuncts: 18 -- out/eval -- (struct){ l: (list){ |((#list){ 0: (int){ int } 1: (int){ int } }, (#list){ 0: (string){ string } 1: (string){ string } }) } l1: (#list){ 0: (string){ "a" } 1: (string){ "b" } } l2: (#list){ 0: (string){ "c" } 1: (string){ "d" } } } cue-lang-cue-db9cc73/cue/testdata/resolve/018_slice.txtar000066400000000000000000000045221474664451600233220ustar00rootroot00000000000000#name: slice #evalPartial -- in.cue -- a: [2][0:0] b: [0][1:1] e1: [][1:1] e2: [0][-1:0] e3: [0][1:0] e4: [0][1:2] e5: 4[1:2] e6: [2]["":] e7: [2][:"9"] -- out/def -- a: [] b: [] e1: _|_ // slice bounds out of range e2: _|_ // negative slice index e3: _|_ // invalid slice index: 1 > 0 e4: _|_ // slice bounds out of range e5: _|_ // cannot slice 4 (type int) e6: _|_ // invalid slice index "" (type string) e7: _|_ // invalid slice index "9" (type string) -- out/legacy-debug -- <0>{a: [], b: [], e1: _|_(1:slice bounds out of range), e2: _|_([0]:negative slice index), e3: _|_([0]:invalid slice index: 1 > 0), e4: _|_(2:slice bounds out of range), e5: _|_(4:cannot slice 4 (type int)), e6: _|_("":invalid slice index "" (type string)), e7: _|_("9":invalid slice index "9" (type string))} -- out/compile -- --- in.cue { a: [ 2, ][0:0] b: [ 0, ][1:1] e1: [][1:1] e2: [ 0, ][-1:0] e3: [ 0, ][1:0] e4: [ 0, ][1:2] e5: 4[1:2] e6: [ 2, ]["":] e7: [ 2, ][:"9"] } -- out/eval/stats -- Leaks: 8 Freed: 10 Reused: 8 Allocs: 10 Retain: 8 Unifications: 18 Conjuncts: 18 Disjuncts: 18 -- out/eval -- Errors: e1: index 1 out of range: ./in.cue:3:5 e2: cannot convert negative number to uint64: ./in.cue:4:5 e3: invalid slice index: 1 > 0: ./in.cue:5:5 e4: index 2 out of range: ./in.cue:6:5 e5: cannot slice 4 (type int): ./in.cue:7:5 e6: cannot use "" (type string) as type int in slice index: ./in.cue:8:5 ./in.cue:8:9 e7: cannot use "9" (type string) as type int in slice index: ./in.cue:9:5 ./in.cue:9:10 Result: (_|_){ // [eval] a: (#list){ } b: (#list){ } e1: (_|_){ // [eval] e1: index 1 out of range: // ./in.cue:3:5 } e2: (_|_){ // [eval] e2: cannot convert negative number to uint64: // ./in.cue:4:5 } e3: (_|_){ // [eval] e3: invalid slice index: 1 > 0: // ./in.cue:5:5 } e4: (_|_){ // [eval] e4: index 2 out of range: // ./in.cue:6:5 } e5: (_|_){ // [eval] e5: cannot slice 4 (type int): // ./in.cue:7:5 } e6: (_|_){ // [eval] e6: cannot use "" (type string) as type int in slice index: // ./in.cue:8:5 // ./in.cue:8:9 } e7: (_|_){ // [eval] e7: cannot use "9" (type string) as type int in slice index: // ./in.cue:9:5 // ./in.cue:9:10 } } cue-lang-cue-db9cc73/cue/testdata/resolve/022_list_unification.txtar000066400000000000000000000014621474664451600255610ustar00rootroot00000000000000#name: list unification #evalPartial -- in.cue -- a: {l: ["foo", v], v: l[1]} b: a & {l: [_, "bar"]} -- out/def -- a: { l: ["foo", v] v: l[1] } b: a & { l: [_, "bar"] } -- out/legacy-debug -- <0>{a: <1>{l: ["foo",<2>.v], v: <2>.l[1]}, b: <3>{l: ["foo","bar"], v: "bar"}} -- out/compile -- --- in.cue { a: { l: [ "foo", 〈1;v〉, ] v: 〈0;l〉[1] } b: (〈0;a〉 & { l: [ _, "bar", ] }) } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 6 Allocs: 5 Retain: 2 Unifications: 11 Conjuncts: 20 Disjuncts: 13 -- out/eval -- (struct){ a: (struct){ l: (#list){ 0: (string){ "foo" } 1: (_){ _ } } v: (_){ _ } } b: (struct){ l: (#list){ 0: (string){ "foo" } 1: (string){ "bar" } } v: (string){ "bar" } } } cue-lang-cue-db9cc73/cue/testdata/resolve/023_correct_error_messages.txtar000066400000000000000000000013341474664451600267560ustar00rootroot00000000000000#name: correct error messages #evalPartial -- in.cue -- a: "a" & 1 -- out/def -- a: _|_ // conflicting values "a" and 1 (mismatched types string and int) -- out/legacy-debug -- <0>{a: _|_(("a" & 1):conflicting values "a" and 1 (mismatched types string and int))} -- out/compile -- --- in.cue { a: ("a" & 1) } -- out/eval/stats -- Leaks: 0 Freed: 2 Reused: 0 Allocs: 2 Retain: 0 Unifications: 2 Conjuncts: 3 Disjuncts: 2 -- out/eval -- Errors: a: conflicting values "a" and 1 (mismatched types string and int): ./in.cue:1:4 ./in.cue:1:10 Result: (_|_){ // [eval] a: (_|_){ // [eval] a: conflicting values "a" and 1 (mismatched types string and int): // ./in.cue:1:4 // ./in.cue:1:10 } } cue-lang-cue-db9cc73/cue/testdata/resolve/024_structs.txtar000066400000000000000000000023361474664451600237300ustar00rootroot00000000000000#name: structs #evalPartial -- in.cue -- a: t & {c: 5} // {c:5,d:15} b: ti & {c: 7} // {c:7,d:21} t: {c: number, d: c * 3} // {c:number,d:number*3} ti: t & {c: int} -- out/def -- a: t & { c: 5 } t: { c: number d: c * 3 } b: ti & { c: 7 } ti: t & { c: int } -- out/legacy-debug -- <0>{a: <1>{c: 5, d: 15}, t: <2>{c: number, d: (<3>.c * 3)}, b: <4>{c: 7, d: 21}, ti: <5>{c: int, d: (<6>.c * 3)}} -- out/compile -- --- in.cue { a: (〈0;t〉 & { c: 5 }) b: (〈0;ti〉 & { c: 7 }) t: { c: number d: (〈0;c〉 * 3) } ti: (〈0;t〉 & { c: int }) } -- out/eval/stats -- Leaks: 0 Freed: 13 Reused: 9 Allocs: 4 Retain: 2 Unifications: 13 Conjuncts: 33 Disjuncts: 15 -- out/eval -- (struct){ a: (struct){ c: (int){ 5 } d: (int){ 15 } } b: (struct){ c: (int){ 7 } d: (int){ 21 } } t: (struct){ c: (number){ number } d: (_|_){ // [incomplete] t.d: non-concrete value number in operand to *: // ./in.cue:3:19 // ./in.cue:3:8 } } ti: (struct){ c: (int){ int } d: (_|_){ // [incomplete] ti.d: non-concrete value int in operand to *: // ./in.cue:3:19 // ./in.cue:3:8 // ./in.cue:4:13 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/025_definitions.txtar000066400000000000000000000130401474664451600245270ustar00rootroot00000000000000#name: definitions #evalPartial -- in.cue -- #Foo: { field: int recursive: { field: string } } // Allowed #Foo1: {field: int} #Foo1: {field2: string} foo: #Foo foo: {feild: 2} foo1: #Foo foo1: { field: 2 recursive: { feild: 2 // Not caught as per spec. TODO: change? } } #Bar: { field: int {[A=_]: int} } bar: #Bar bar: {feild: 2} #Mixed: string Mixed: string mixedRec: {#Mixed: string} mixedRec: {Mixed: string} -- out/def -- #Foo: { field: int recursive: { field: string } } // Allowed #Foo1: { field: int field2: string } foo: _|_ // field "feild" not allowed in closed struct foo1: #Foo & { field: 2 recursive: { feild: 2 } } #Bar: { {[A=string]: int} field: int } bar: #Bar & { feild: 2 } #Mixed: string Mixed: string mixedRec: { #Mixed: string Mixed: string } -- out/legacy-debug -- <0>{#Foo: <1>C{field: int, recursive: <2>C{field: string}}, #Foo1: <3>C{field: int, field2: string}, foo: _|_(2:field "feild" not allowed in closed struct), foo1: <4>C{field: 2, recursive: _|_(2:field "feild" not allowed in closed struct)}, #Bar: <5>{[]: <6>(A: string)->int, field: int}, bar: <7>{[]: <8>(A: string)->int, field: int, feild: 2}, #Mixed: string, Mixed: string, mixedRec: <9>{#Mixed: string, Mixed: string}} -- out/compile -- --- in.cue { #Foo: { field: int recursive: { field: string } } #Foo1: { field: int } #Foo1: { field2: string } foo: 〈0;#Foo〉 foo: { feild: 2 } foo1: 〈0;#Foo〉 foo1: { field: 2 recursive: { feild: 2 } } #Bar: { field: int { [_]: int } } bar: 〈0;#Bar〉 bar: { feild: 2 } #Mixed: string Mixed: string mixedRec: { #Mixed: string } mixedRec: { Mixed: string } } -- out/eval/stats -- Leaks: 0 Freed: 28 Reused: 24 Allocs: 4 Retain: 0 Unifications: 28 Conjuncts: 43 Disjuncts: 28 -- out/evalalpha -- Errors: foo1.recursive.feild: field not allowed: ./in.cue:19:3 foo.feild: field not allowed: ./in.cue:12:6 ./in.cue:13:7 Result: (_|_){ // [eval] #Foo: (#struct){ field: (int){ int } recursive: (#struct){ field: (string){ string } } } #Foo1: (#struct){ field: (int){ int } field2: (string){ string } } foo: (_|_){ // [eval] feild: (_|_){ // [eval] foo.feild: field not allowed: // ./in.cue:12:6 // ./in.cue:13:7 } field: (int){ int } recursive: (#struct){ field: (string){ string } } } foo1: (_|_){ // [eval] field: (int){ 2 } recursive: (_|_){ // [eval] feild: (_|_){ // [eval] foo1.recursive.feild: field not allowed: // ./in.cue:19:3 } field: (string){ string } } } #Bar: (#struct){ field: (int){ int } } bar: (#struct){ feild: (int){ 2 } field: (int){ int } } #Mixed: (string){ string } Mixed: (string){ string } mixedRec: (struct){ #Mixed: (string){ string } Mixed: (string){ string } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,12 +1,9 @@ Errors: +foo1.recursive.feild: field not allowed: + ./in.cue:19:3 foo.feild: field not allowed: - ./in.cue:1:7 ./in.cue:12:6 ./in.cue:13:7 -foo1.recursive.feild: field not allowed: - ./in.cue:3:13 - ./in.cue:15:7 - ./in.cue:19:3 Result: (_|_){ @@ -23,16 +20,15 @@ } foo: (_|_){ // [eval] - field: (int){ int } - recursive: (#struct){ - field: (string){ string } - } feild: (_|_){ // [eval] foo.feild: field not allowed: - // ./in.cue:1:7 // ./in.cue:12:6 // ./in.cue:13:7 } + field: (int){ int } + recursive: (#struct){ + field: (string){ string } + } } foo1: (_|_){ // [eval] @@ -39,13 +35,11 @@ field: (int){ 2 } recursive: (_|_){ // [eval] - field: (string){ string } feild: (_|_){ // [eval] foo1.recursive.feild: field not allowed: - // ./in.cue:3:13 - // ./in.cue:15:7 // ./in.cue:19:3 } + field: (string){ string } } } #Bar: (#struct){ @@ -52,8 +46,8 @@ field: (int){ int } } bar: (#struct){ - field: (int){ int } feild: (int){ 2 } + field: (int){ int } } #Mixed: (string){ string } Mixed: (string){ string } -- diff/todo/p2 -- Positions / reordering. -- out/eval -- Errors: foo.feild: field not allowed: ./in.cue:1:7 ./in.cue:12:6 ./in.cue:13:7 foo1.recursive.feild: field not allowed: ./in.cue:3:13 ./in.cue:15:7 ./in.cue:19:3 Result: (_|_){ // [eval] #Foo: (#struct){ field: (int){ int } recursive: (#struct){ field: (string){ string } } } #Foo1: (#struct){ field: (int){ int } field2: (string){ string } } foo: (_|_){ // [eval] field: (int){ int } recursive: (#struct){ field: (string){ string } } feild: (_|_){ // [eval] foo.feild: field not allowed: // ./in.cue:1:7 // ./in.cue:12:6 // ./in.cue:13:7 } } foo1: (_|_){ // [eval] field: (int){ 2 } recursive: (_|_){ // [eval] field: (string){ string } feild: (_|_){ // [eval] foo1.recursive.feild: field not allowed: // ./in.cue:3:13 // ./in.cue:15:7 // ./in.cue:19:3 } } } #Bar: (#struct){ field: (int){ int } } bar: (#struct){ field: (int){ int } feild: (int){ 2 } } #Mixed: (string){ string } Mixed: (string){ string } mixedRec: (struct){ #Mixed: (string){ string } Mixed: (string){ string } } } cue-lang-cue-db9cc73/cue/testdata/resolve/027_new-style_definitions.txtar000066400000000000000000000032701474664451600265440ustar00rootroot00000000000000#name: new-style definitions #evalPartial -- in.cue -- #Foo: { a: 1 b: int } "#Foo": #Foo & {b: 1} bulk: {[string]: string} & { #def: 4 // Different namespace, so bulk option does not apply. _hid: 3 a: "foo" } -- out/def -- "#Foo": #Foo & { b: 1 } #Foo: { a: 1 b: int } bulk: { {[string]: string} a: "foo" #def: 4 _hid: 3 } -- out/export -- "#Foo": { a: 1 b: 1 } bulk: { a: "foo" } -- out/yaml -- '#Foo': a: 1 b: 1 bulk: a: foo -- out/json -- {"#Foo":{"a":1,"b":1},"bulk":{"a":"foo"}} -- out/legacy-debug -- <0>{"#Foo": <1>C{a: 1, b: 1}, #Foo: <2>C{a: 1, b: int}, bulk: <3>{[]: <4>(_: string)->string, a: "foo", #def: 4, _hid: 3}} -- out/compile -- --- in.cue { #Foo: { a: 1 b: int } "#Foo": (〈0;#Foo〉 & { b: 1 }) bulk: ({ [string]: string } & { #def: 4 _hid: 3 a: "foo" }) } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 8 Allocs: 3 Retain: 0 Unifications: 11 Conjuncts: 16 Disjuncts: 11 -- out/evalalpha -- (struct){ #Foo: (#struct){ a: (int){ 1 } b: (int){ int } } "#Foo": (#struct){ b: (int){ 1 } a: (int){ 1 } } bulk: (struct){ #def: (int){ 4 } _hid: (int){ 3 } a: (string){ "foo" } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,8 +4,8 @@ b: (int){ int } } "#Foo": (#struct){ - a: (int){ 1 } b: (int){ 1 } + a: (int){ 1 } } bulk: (struct){ #def: (int){ 4 } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ #Foo: (#struct){ a: (int){ 1 } b: (int){ int } } "#Foo": (#struct){ a: (int){ 1 } b: (int){ 1 } } bulk: (struct){ #def: (int){ 4 } _hid: (int){ 3 } a: (string){ "foo" } } } 029_non-closed_definition_carries_over_closedness_to_enclosed_template.txtar000066400000000000000000000122121474664451600376500ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/resolve#name: non-closed definition carries over closedness to enclosed template #evalPartial -- in.cue -- #S: { [string]: {a: int} } a: #S & { v: {b: int} } #Q: { [string]: {a: int} | {b: int} } b: #Q & { w: {c: int} } #R: { [string]: [{a: int}, {b: int}] } c: #R & { w: [{d: int}, ...] } -- out/def -- #S: { [string]: { a: int } } a: #S & { v: { b: int } } b: #Q & { w: { c: int } } #Q: { [string]: { a: int } | { b: int } } c: #R & { w: [{ d: int }, ...] } #R: { [string]: [{ a: int }, { b: int }] } -- out/legacy-debug -- <0>{#S: <1>{[]: <2>(_: string)-><3>C{a: int}, }, a: <4>{[]: <5>(_: string)-><6>C{a: int}, v: _|_(int:field "b" not allowed in closed struct)}, b: <7>{[]: <8>(_: string)->(<9>C{a: int} | <10>C{b: int}), w: _|_(int:empty disjunction: field "c" not allowed in closed struct)}, #Q: <11>{[]: <12>(_: string)->(<13>C{a: int} | <14>C{b: int}), }, c: <15>{[]: <16>(_: string)->[<17>C{a: int},<18>C{b: int}], w: [_|_(int:field "d" not allowed in closed struct),<19>C{b: int}]}, #R: <20>{[]: <21>(_: string)->[<22>C{a: int},<23>C{b: int}], }} -- out/compile -- --- in.cue { #S: { [string]: { a: int } } a: (〈0;#S〉 & { v: { b: int } }) #Q: { [string]: ({ a: int }|{ b: int }) } b: (〈0;#Q〉 & { w: { c: int } }) #R: { [string]: [ { a: int }, { b: int }, ] } c: (〈0;#R〉 & { w: [ { d: int }, ..., ] }) } -- out/eval/stats -- Leaks: 0 Freed: 23 Reused: 18 Allocs: 5 Retain: 0 Unifications: 21 Conjuncts: 34 Disjuncts: 23 -- out/evalalpha -- Errors: a.v.b: field not allowed: ./in.cue:5:6 b.w.c: field not allowed: ./in.cue:11:6 c.w.0.d: field not allowed: ./in.cue:17:7 Result: (_|_){ // [eval] #S: (#struct){ } a: (_|_){ // [eval] v: (_|_){ // [eval] b: (_|_){ // [eval] a.v.b: field not allowed: // ./in.cue:5:6 } a: (int){ int } } } #Q: (#struct){ } b: (_|_){ // [eval] w: (_|_){ // [eval] b.w.c: field not allowed: // ./in.cue:11:6 c: (int){ int } } } #R: (#struct){ } c: (_|_){ // [eval] w: (_|_){ // [eval] 0: (_|_){ // [eval] d: (_|_){ // [eval] c.w.0.d: field not allowed: // ./in.cue:17:7 } a: (int){ int } } 1: (#struct){ b: (int){ int } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,16 +1,9 @@ Errors: a.v.b: field not allowed: - ./in.cue:2:12 - ./in.cue:4:4 ./in.cue:5:6 b.w.c: field not allowed: - ./in.cue:8:12 - ./in.cue:10:4 ./in.cue:11:6 c.w.0.d: field not allowed: - ./in.cue:14:12 - ./in.cue:14:13 - ./in.cue:16:4 ./in.cue:17:7 Result: @@ -24,8 +17,6 @@ // [eval] b: (_|_){ // [eval] a.v.b: field not allowed: - // ./in.cue:2:12 - // ./in.cue:4:4 // ./in.cue:5:6 } a: (int){ int } @@ -37,17 +28,8 @@ // [eval] w: (_|_){ // [eval] b.w.c: field not allowed: - // ./in.cue:8:12 - // ./in.cue:10:4 // ./in.cue:11:6 - c: (_|_){ - // [eval] b.w.c: field not allowed: - // ./in.cue:8:12 - // ./in.cue:8:23 - // ./in.cue:10:4 - // ./in.cue:11:6 - } - b: (int){ int } + c: (int){ int } } } #R: (#struct){ @@ -60,9 +42,6 @@ // [eval] d: (_|_){ // [eval] c.w.0.d: field not allowed: - // ./in.cue:14:12 - // ./in.cue:14:13 - // ./in.cue:16:4 // ./in.cue:17:7 } a: (int){ int } -- diff/todo/p3 -- Missing error positions. -- out/eval -- Errors: a.v.b: field not allowed: ./in.cue:2:12 ./in.cue:4:4 ./in.cue:5:6 b.w.c: field not allowed: ./in.cue:8:12 ./in.cue:10:4 ./in.cue:11:6 c.w.0.d: field not allowed: ./in.cue:14:12 ./in.cue:14:13 ./in.cue:16:4 ./in.cue:17:7 Result: (_|_){ // [eval] #S: (#struct){ } a: (_|_){ // [eval] v: (_|_){ // [eval] b: (_|_){ // [eval] a.v.b: field not allowed: // ./in.cue:2:12 // ./in.cue:4:4 // ./in.cue:5:6 } a: (int){ int } } } #Q: (#struct){ } b: (_|_){ // [eval] w: (_|_){ // [eval] b.w.c: field not allowed: // ./in.cue:8:12 // ./in.cue:10:4 // ./in.cue:11:6 c: (_|_){ // [eval] b.w.c: field not allowed: // ./in.cue:8:12 // ./in.cue:8:23 // ./in.cue:10:4 // ./in.cue:11:6 } b: (int){ int } } } #R: (#struct){ } c: (_|_){ // [eval] w: (_|_){ // [eval] 0: (_|_){ // [eval] d: (_|_){ // [eval] c.w.0.d: field not allowed: // ./in.cue:14:12 // ./in.cue:14:13 // ./in.cue:16:4 // ./in.cue:17:7 } a: (int){ int } } 1: (#struct){ b: (int){ int } } } } } cue-lang-cue-db9cc73/cue/testdata/resolve/030_definitions_with_disjunctions.txtar000066400000000000000000000063431474664451600303620ustar00rootroot00000000000000#name: definitions with disjunctions #evalPartial -- in.cue -- #Foo: { field: int {a: 1} | {b: 2} } foo: #Foo foo: {a: 1} bar: #Foo bar: {c: 2} baz: #Foo baz: {b: 2} -- out/def -- #Foo: { field: int a: 1 } | { field: int b: 2 } foo: #Foo & { a: 1 } bar: _|_ // baz: #Foo & { b: 2 } -- out/legacy-debug -- <0>{#Foo: (<1>C{field: int, a: 1} | <2>C{field: int, b: 2}), foo: <3>C{field: int, a: 1}, bar: _|_(2:empty disjunction: field "c" not allowed in closed struct), baz: <4>C{field: int, b: 2}} -- out/compile -- --- in.cue { #Foo: { field: int ({ a: 1 }|{ b: 2 }) } foo: 〈0;#Foo〉 foo: { a: 1 } bar: 〈0;#Foo〉 bar: { c: 2 } baz: 〈0;#Foo〉 baz: { b: 2 } } -- out/eval/stats -- Leaks: 0 Freed: 33 Reused: 28 Allocs: 5 Retain: 0 Unifications: 25 Conjuncts: 45 Disjuncts: 33 -- out/evalalpha -- Errors: bar.c: field not allowed: ./in.cue:12:7 Result: (_|_){ // [eval] #Foo: (#struct){ |((#struct){ field: (int){ int } a: (int){ 1 } }, (#struct){ field: (int){ int } b: (int){ 2 } }) } foo: (#struct){ a: (int){ 1 } field: (int){ int } } bar: (_|_){ // [eval] bar.c: field not allowed: // ./in.cue:12:7 c: (int){ 2 } field: (int){ int } } baz: (#struct){ b: (int){ 2 } field: (int){ int } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,8 +1,5 @@ Errors: bar.c: field not allowed: - ./in.cue:1:7 - ./in.cue:4:2 - ./in.cue:11:6 ./in.cue:12:7 Result: @@ -16,28 +13,17 @@ b: (int){ 2 } }) } foo: (#struct){ - field: (int){ int } a: (int){ 1 } + field: (int){ int } } bar: (_|_){ // [eval] bar.c: field not allowed: - // ./in.cue:1:7 - // ./in.cue:4:2 - // ./in.cue:11:6 // ./in.cue:12:7 - field: (int){ int } - c: (_|_){ - // [eval] bar.c: field not allowed: - // ./in.cue:1:7 - // ./in.cue:4:2 - // ./in.cue:5:2 - // ./in.cue:11:6 - // ./in.cue:12:7 - } - b: (int){ 2 } + c: (int){ 2 } + field: (int){ int } } baz: (#struct){ - field: (int){ int } - b: (int){ 2 } + b: (int){ 2 } + field: (int){ int } } } -- diff/todo/p2 -- Missing error positions and reorderings. -- diff/explanation -- bar.b: removed in new evaluator. This is correct. In the old evaluator this addition was spurious. -- out/eval -- Errors: bar.c: field not allowed: ./in.cue:1:7 ./in.cue:4:2 ./in.cue:11:6 ./in.cue:12:7 Result: (_|_){ // [eval] #Foo: (#struct){ |((#struct){ field: (int){ int } a: (int){ 1 } }, (#struct){ field: (int){ int } b: (int){ 2 } }) } foo: (#struct){ field: (int){ int } a: (int){ 1 } } bar: (_|_){ // [eval] bar.c: field not allowed: // ./in.cue:1:7 // ./in.cue:4:2 // ./in.cue:11:6 // ./in.cue:12:7 field: (int){ int } c: (_|_){ // [eval] bar.c: field not allowed: // ./in.cue:1:7 // ./in.cue:4:2 // ./in.cue:5:2 // ./in.cue:11:6 // ./in.cue:12:7 } b: (int){ 2 } } baz: (#struct){ field: (int){ int } b: (int){ 2 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/031_definitions_with_disjunctions_recurisive.txtar000066400000000000000000000016571474664451600326260ustar00rootroot00000000000000#name: definitions with disjunctions recurisive #evalPartial -- in.cue -- #Foo: { x: { field: int {a: 1} | {b: 2} } x: c: 3 } -- out/def -- #Foo: { x: { field: int a: 1 c: 3 } | { field: int b: 2 c: 3 } } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/legacy-debug -- <0>{#Foo: <1>C{x: (<2>C{field: int, a: 1, c: 3} | <3>C{field: int, b: 2, c: 3})}} -- out/compile -- --- in.cue { #Foo: { x: { field: int ({ a: 1 }|{ b: 2 }) } x: { c: 3 } } } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 5 Allocs: 6 Retain: 0 Unifications: 9 Conjuncts: 13 Disjuncts: 11 -- out/eval -- (struct){ #Foo: (#struct){ x: (#struct){ |((#struct){ field: (int){ int } c: (int){ 3 } a: (int){ 1 } }, (#struct){ field: (int){ int } c: (int){ 3 } b: (int){ 2 } }) } } } cue-lang-cue-db9cc73/cue/testdata/resolve/033_top-level_definition_with_struct_and_disjunction.txtar000066400000000000000000000020141474664451600342230ustar00rootroot00000000000000#name: top-level definition with struct and disjunction #evalPartial -- in.cue -- #def: { Type: string Text: string Size: int } #def: { Type: "B" Size: 0 } | { Type: "A" Size: 1 } -- out/def -- #def: { Size: 0 Type: "B" Text: string } | { Size: 1 Type: "A" Text: string } -- out/export -- -- out/yaml -- {} -- out/json -- {} -- out/legacy-debug -- <0>{#def: (<1>C{Size: (0 & int), Type: ("B" & string), Text: string} | <2>C{Size: (1 & int), Type: ("A" & string), Text: string})} -- out/compile -- --- in.cue { #def: { Type: string Text: string Size: int } #def: ({ Type: "B" Size: 0 }|{ Type: "A" Size: 1 }) } -- out/eval/stats -- Leaks: 0 Freed: 10 Reused: 5 Allocs: 5 Retain: 0 Unifications: 8 Conjuncts: 15 Disjuncts: 10 -- out/eval -- (struct){ #def: (#struct){ |((#struct){ Type: (string){ "B" } Text: (string){ string } Size: (int){ 0 } }, (#struct){ Type: (string){ "A" } Text: (string){ string } Size: (int){ 1 } }) } } cue-lang-cue-db9cc73/cue/testdata/resolve/034_closing_structs.txtar000066400000000000000000000071471474664451600254540ustar00rootroot00000000000000#name: closing structs #evalPartial -- in.cue -- op: {x: int} // {x: int} ot: {x: int, ...} // {x: int, ...} cp: close({x: int}) // closed({x: int}) ct: close({x: int, ...}) // {x: int, ...} opot: op & ot // {x: int, ...} otop: ot & op // {x: int, ...} opcp: op & cp // closed({x: int}) cpop: cp & op // closed({x: int}) opct: op & ct // {x: int, ...} ctop: ct & op // {x: int, ...} otcp: ot & cp // closed({x: int}) cpot: cp & ot // closed({x: int}) otct: ot & ct // {x: int, ...} ctot: ct & ot // {x: int, ...} cpct: cp & ct // closed({x: int}) ctcp: ct & cp // closed({x: int}) ctct: ct & ct // {x: int, ...} -- out/def -- op: { x: int } ot: { x: int ... } cp: close({ x: int }) ct: { x: int ... } opot: op & ot otop: ot & op opcp: op & cp cpop: cp & op opct: op & ct ctop: ct & op otcp: ot & cp cpot: cp & ot otct: ot & ct ctot: ct & ot cpct: cp & ct ctcp: ct & cp ctct: ct & ct -- out/legacy-debug -- <0>{op: <1>{x: int}, ot: <2>{x: int, ...}, cp: <3>C{x: int}, ct: <4>{x: int, ...}, opot: <5>{x: int, ...}, otop: <6>{x: int, ...}, opcp: <7>C{x: int}, cpop: <8>C{x: int}, opct: <9>{x: int, ...}, ctop: <10>{x: int, ...}, otcp: <11>C{x: int}, cpot: <12>C{x: int}, otct: <13>{x: int, ...}, ctot: <14>{x: int, ...}, cpct: <15>C{x: int}, ctcp: <16>C{x: int}, ctct: <17>{x: int, ...}} -- out/eval/stats -- Leaks: 15 Freed: 35 Reused: 32 Allocs: 18 Retain: 15 Unifications: 50 Conjuncts: 115 Disjuncts: 50 -- out/evalalpha -- (struct){ op: (struct){ x: (int){ int } } ot: (struct){ x: (int){ int } } cp: (#struct){ x: (int){ int } } ct: (#struct){ x: (int){ int } } opot: (struct){ x: (int){ int } } otop: (struct){ x: (int){ int } } opcp: (#struct){ x: (int){ int } } cpop: (#struct){ x: (int){ int } } opct: (#struct){ x: (int){ int } } ctop: (#struct){ x: (int){ int } } otcp: (#struct){ x: (int){ int } } cpot: (#struct){ x: (int){ int } } otct: (#struct){ x: (int){ int } } ctot: (#struct){ x: (int){ int } } cpct: (#struct){ x: (int){ int } } ctcp: (#struct){ x: (int){ int } } ctct: ~(ct) } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -47,7 +47,5 @@ ctcp: (#struct){ x: (int){ int } } - ctct: (#struct){ - x: (int){ int } - } + ctct: ~(ct) } -- out/eval -- (struct){ op: (struct){ x: (int){ int } } ot: (struct){ x: (int){ int } } cp: (#struct){ x: (int){ int } } ct: (#struct){ x: (int){ int } } opot: (struct){ x: (int){ int } } otop: (struct){ x: (int){ int } } opcp: (#struct){ x: (int){ int } } cpop: (#struct){ x: (int){ int } } opct: (#struct){ x: (int){ int } } ctop: (#struct){ x: (int){ int } } otcp: (#struct){ x: (int){ int } } cpot: (#struct){ x: (int){ int } } otct: (#struct){ x: (int){ int } } ctot: (#struct){ x: (int){ int } } cpct: (#struct){ x: (int){ int } } ctcp: (#struct){ x: (int){ int } } ctct: (#struct){ x: (int){ int } } } -- out/compile -- --- in.cue { op: { x: int } ot: { x: int ... } cp: close({ x: int }) ct: close({ x: int ... }) opot: (〈0;op〉 & 〈0;ot〉) otop: (〈0;ot〉 & 〈0;op〉) opcp: (〈0;op〉 & 〈0;cp〉) cpop: (〈0;cp〉 & 〈0;op〉) opct: (〈0;op〉 & 〈0;ct〉) ctop: (〈0;ct〉 & 〈0;op〉) otcp: (〈0;ot〉 & 〈0;cp〉) cpot: (〈0;cp〉 & 〈0;ot〉) otct: (〈0;ot〉 & 〈0;ct〉) ctot: (〈0;ct〉 & 〈0;ot〉) cpct: (〈0;cp〉 & 〈0;ct〉) ctcp: (〈0;ct〉 & 〈0;cp〉) ctct: (〈0;ct〉 & 〈0;ct〉) } cue-lang-cue-db9cc73/cue/testdata/resolve/035_excluded_embedding_from_closing.txtar000066400000000000000000000076121474664451600305610ustar00rootroot00000000000000#name: excluded embedding from closing #evalPartial -- in.cue -- #S: { a: {c: int} { c: {d: int} } let B = {open: int} b: B } V: #S & { c: e: int b: extra: int } -- out/def -- #S: { a: { c: int } c: { d: int ... } b: { open: int ... } } V: #S & { c: { e: int } b: { extra: int } } -- out/legacy-debug -- <0>{#S: <1>C{a: <2>C{c: int}, c: <3>{d: int}, b: <4>{open: int}}, V: <5>C{a: <6>C{c: int}, c: <7>{d: int, e: int}, b: <8>{open: int, extra: int}}} -- out/compile -- --- in.cue { #S: { a: { c: int } { c: { d: int } } let B#1 = { open: int } b: 〈0;let B#1〉 } V: (〈0;#S〉 & { c: { e: int } b: { extra: int } }) } -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 17 Allocs: 4 Retain: 0 Unifications: 21 Conjuncts: 29 Disjuncts: 21 -- out/evalalpha -- Errors: V.b.extra: field not allowed: ./in.cue:11:5 V.c.e: field not allowed: ./in.cue:10:5 Result: (_|_){ // [eval] #S: (#struct){ a: (#struct){ c: (int){ int } } c: (#struct){ d: (int){ int } } let B#1 = (#struct){ open: (int){ int } } b: (#struct){ open: (int){ int } } } V: (_|_){ // [eval] c: (_|_){ // [eval] e: (_|_){ // [eval] V.c.e: field not allowed: // ./in.cue:10:5 } d: (int){ int } } b: (_|_){ // [eval] extra: (_|_){ // [eval] V.b.extra: field not allowed: // ./in.cue:11:5 } open: (int){ int } } a: (#struct){ c: (int){ int } } let B#1 = (#struct){ open: (int){ int } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,13 +1,7 @@ Errors: V.b.extra: field not allowed: - ./in.cue:6:10 - ./in.cue:7:5 - ./in.cue:9:4 ./in.cue:11:5 V.c.e: field not allowed: - ./in.cue:3:2 - ./in.cue:4:6 - ./in.cue:9:4 ./in.cue:10:5 Result: @@ -29,33 +23,27 @@ } V: (_|_){ // [eval] - a: (#struct){ - c: (int){ int } - } c: (_|_){ // [eval] - d: (int){ int } e: (_|_){ // [eval] V.c.e: field not allowed: - // ./in.cue:3:2 - // ./in.cue:4:6 - // ./in.cue:9:4 // ./in.cue:10:5 } - } - let B#1 = (#struct){ - open: (int){ int } + d: (int){ int } } b: (_|_){ // [eval] - open: (int){ int } extra: (_|_){ // [eval] V.b.extra: field not allowed: - // ./in.cue:6:10 - // ./in.cue:7:5 - // ./in.cue:9:4 // ./in.cue:11:5 } + open: (int){ int } + } + a: (#struct){ + c: (int){ int } + } + let B#1 = (#struct){ + open: (int){ int } } } } -- diff/todo/p2 -- Positions. Reordering. -- out/eval -- Errors: V.b.extra: field not allowed: ./in.cue:6:10 ./in.cue:7:5 ./in.cue:9:4 ./in.cue:11:5 V.c.e: field not allowed: ./in.cue:3:2 ./in.cue:4:6 ./in.cue:9:4 ./in.cue:10:5 Result: (_|_){ // [eval] #S: (#struct){ a: (#struct){ c: (int){ int } } c: (#struct){ d: (int){ int } } let B#1 = (#struct){ open: (int){ int } } b: (#struct){ open: (int){ int } } } V: (_|_){ // [eval] a: (#struct){ c: (int){ int } } c: (_|_){ // [eval] d: (int){ int } e: (_|_){ // [eval] V.c.e: field not allowed: // ./in.cue:3:2 // ./in.cue:4:6 // ./in.cue:9:4 // ./in.cue:10:5 } } let B#1 = (#struct){ open: (int){ int } } b: (_|_){ // [eval] open: (int){ int } extra: (_|_){ // [eval] V.b.extra: field not allowed: // ./in.cue:6:10 // ./in.cue:7:5 // ./in.cue:9:4 // ./in.cue:11:5 } } } } cue-lang-cue-db9cc73/cue/testdata/resolve/038_incomplete_comprehensions.txtar000066400000000000000000000021751474664451600275020ustar00rootroot00000000000000#name: incomplete comprehensions #evalPartial -- in.cue -- A: { for v in src { "\(v)": v } src: _ if true { baz: "baz" } } B: A & { src: ["foo", "bar"] } -- out/def -- A: { src: _ baz: "baz" for v in src { "\(v)": v } } B: A & { src: ["foo", "bar"] } -- out/legacy-debug -- <0>{A: <1>{src: _, baz: "baz" <2>for _, v in <3>.src yield <4>{""+<2>.v+"": <2>.v}}, B: <5>{src: ["foo","bar"], baz: "baz", foo: "foo", bar: "bar"}} -- out/compile -- --- in.cue { A: { for _, v in 〈0;src〉 { "\(〈1;v〉)": 〈1;v〉 } src: _ if true { baz: "baz" } } B: (〈0;A〉 & { src: [ "foo", "bar", ] }) } -- out/eval/stats -- Leaks: 0 Freed: 11 Reused: 6 Allocs: 5 Retain: 9 Unifications: 11 Conjuncts: 16 Disjuncts: 16 -- out/eval -- (struct){ A: (_|_){ // [incomplete] A: cannot range over src (incomplete type _): // ./in.cue:2:11 src: (_){ _ } baz: (string){ "baz" } } B: (struct){ src: (#list){ 0: (string){ "foo" } 1: (string){ "bar" } } baz: (string){ "baz" } foo: (string){ "foo" } bar: (string){ "bar" } } } cue-lang-cue-db9cc73/cue/testdata/resolve/039_reference_to_root.txtar000066400000000000000000000041671474664451600257360ustar00rootroot00000000000000#name: reference to root #evalPartial -- in.cue -- a: {b: int} c: a & { b: 100 d: a.b + 3 // do not resolve as c != a. } x: { b: int c: b + 5 } y: x & { b: 100 // c should resolve to 105 } v: { b: int c: v.b + 5 // reference starting from copied node. } w: v & {b: 100} wp: v & {b: 100} -- out/def -- x: { b: int c: b + 5 } y: x & { b: 100 } a: { b: int } c: a & { b: 100 d: a.b + 3 } v: { b: int c: v.b + 5 } w: v & { b: 100 } wp: v & { b: 100 } -- out/legacy-debug -- <0>{x: <1>{b: int, c: (<2>.b + 5)}, y: <3>{b: 100, c: 105}, a: <4>{b: int}, c: <5>{b: 100, d: (<6>.a.b + 3)}, v: <7>{b: int, c: (<6>.v.b + 5)}, w: <8>{b: 100, c: (<6>.v.b + 5)}, wp: <9>{b: 100, c: (<6>.v.b + 5)}} -- out/compile -- --- in.cue { a: { b: int } c: (〈0;a〉 & { b: 100 d: (〈1;a〉.b + 3) }) x: { b: int c: (〈0;b〉 + 5) } y: (〈0;x〉 & { b: 100 }) v: { b: int c: (〈1;v〉.b + 5) } w: (〈0;v〉 & { b: 100 }) wp: (〈0;v〉 & { b: 100 }) } -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 18 Allocs: 3 Retain: 0 Unifications: 21 Conjuncts: 53 Disjuncts: 21 -- out/eval -- (struct){ a: (struct){ b: (int){ int } } c: (struct){ b: (int){ 100 } d: (_|_){ // [incomplete] c.d: non-concrete value int in operand to +: // ./in.cue:4:5 // ./in.cue:1:8 } } x: (struct){ b: (int){ int } c: (_|_){ // [incomplete] x.c: non-concrete value int in operand to +: // ./in.cue:8:5 // ./in.cue:7:5 } } y: (struct){ b: (int){ 100 } c: (int){ 105 } } v: (struct){ b: (int){ int } c: (_|_){ // [incomplete] v.c: non-concrete value int in operand to +: // ./in.cue:16:5 // ./in.cue:15:5 } } w: (struct){ b: (int){ 100 } c: (_|_){ // [incomplete] w.c: non-concrete value int in operand to +: // ./in.cue:16:5 // ./in.cue:15:5 } } wp: (struct){ b: (int){ 100 } c: (_|_){ // [incomplete] wp.c: non-concrete value int in operand to +: // ./in.cue:16:5 // ./in.cue:15:5 } } } cue-lang-cue-db9cc73/cue/testdata/resolve/040_references_from_template_to_concrete.txtar000066400000000000000000000044341474664451600316430ustar00rootroot00000000000000#name: references from template to concrete #evalPartial -- in.cue -- res: [t] t: [X=string]: { a: c + b.str b: str: string c: "X" } t: x: {b: str: "DDDD"} -- out/def -- res: [t] t: { {[X=string]: { a: c + b.str, c: "X", b: { str: string } }} x: { a: "XDDDD" c: "X" b: { str: "DDDD" } } } -- out/export -- res: [{ x: { a: "XDDDD" c: "X" b: { str: "DDDD" } } }] t: { x: { a: "XDDDD" c: "X" b: { str: "DDDD" } } } -- out/yaml -- res: - x: a: XDDDD c: X b: str: DDDD t: x: a: XDDDD c: X b: str: DDDD -- out/json -- {"res":[{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}],"t":{"x":{"a":"XDDDD","c":"X","b":{"str":"DDDD"}}}} -- out/legacy-debug -- <0>{res: [<1>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <5>{a: "XDDDD", c: "X", b: <6>{str: "DDDD"}}}], t: <7>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <8>{a: "XDDDD", c: "X", b: <9>{str: "DDDD"}}}} -- out/compile -- --- in.cue { res: [ 〈1;t〉, ] t: { [string]: { a: (〈0;c〉 + 〈0;b〉.str) b: { str: string } c: "X" } } t: { x: { b: { str: "DDDD" } } } } -- out/eval/stats -- Leaks: 0 Freed: 14 Reused: 7 Allocs: 7 Retain: 3 Unifications: 14 Conjuncts: 21 Disjuncts: 15 -- out/evalalpha -- (struct){ res: (#list){ 0: ~(t) } t: (struct){ x: (struct){ b: (struct){ str: (string){ "DDDD" } } a: (string){ "XDDDD" } c: (string){ "X" } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,14 +1,6 @@ (struct){ res: (#list){ - 0: (struct){ - x: (struct){ - b: (struct){ - str: (string){ "DDDD" } - } - a: (string){ "XDDDD" } - c: (string){ "X" } - } - } + 0: ~(t) } t: (struct){ x: (struct){ -- out/eval -- (struct){ res: (#list){ 0: (struct){ x: (struct){ b: (struct){ str: (string){ "DDDD" } } a: (string){ "XDDDD" } c: (string){ "X" } } } } t: (struct){ x: (struct){ b: (struct){ str: (string){ "DDDD" } } a: (string){ "XDDDD" } c: (string){ "X" } } } } cue-lang-cue-db9cc73/cue/testdata/resolve/043_diamond-shaped_constraints.txtar000066400000000000000000000045521474664451600275300ustar00rootroot00000000000000#name: diamond-shaped constraints #evalPartial -- in.cue -- S: { A: { a: 1 } B: A & { b: 2 } } T: S & {// S == { A: { a:1 }, B: { a:1, b:2 } } A: { c: 3 } B: { d: 4 // Combines constraints S.A, S.B, T.A, and T.B // S.B & A } } -- out/def -- T: S & { A: { c: 3 } B: { d: 4 } } S: { A: { a: 1 } B: A & { b: 2 } } -- out/export -- T: { A: { a: 1 c: 3 } B: { a: 1 b: 2 c: 3 d: 4 } } S: { A: { a: 1 } B: { a: 1 b: 2 } } -- out/yaml -- T: A: a: 1 c: 3 B: a: 1 b: 2 c: 3 d: 4 S: A: a: 1 B: a: 1 b: 2 -- out/json -- {"T":{"A":{"a":1,"c":3},"B":{"a":1,"b":2,"c":3,"d":4}},"S":{"A":{"a":1},"B":{"a":1,"b":2}}} -- out/legacy-debug -- <0>{T: <1>{A: <2>{a: 1, c: 3}, B: <3>{a: 1, b: 2, c: 3, d: 4}}, S: <4>{A: <5>{a: 1}, B: <6>{a: 1, b: 2}}} -- out/compile -- --- in.cue { S: { A: { a: 1 } B: (〈0;A〉 & { b: 2 }) } T: (〈0;S〉 & { A: { c: 3 } B: { d: 4 } }) } -- out/eval/stats -- Leaks: 0 Freed: 16 Reused: 12 Allocs: 4 Retain: 0 Unifications: 16 Conjuncts: 25 Disjuncts: 16 -- out/evalalpha -- (struct){ S: (struct){ A: (struct){ a: (int){ 1 } } B: (struct){ b: (int){ 2 } a: (int){ 1 } } } T: (struct){ A: (struct){ c: (int){ 3 } a: (int){ 1 } } B: (struct){ d: (int){ 4 } b: (int){ 2 } c: (int){ 3 } a: (int){ 1 } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -4,20 +4,20 @@ a: (int){ 1 } } B: (struct){ - a: (int){ 1 } - b: (int){ 2 } + b: (int){ 2 } + a: (int){ 1 } } } T: (struct){ A: (struct){ - a: (int){ 1 } - c: (int){ 3 } - } - B: (struct){ - a: (int){ 1 } - c: (int){ 3 } - b: (int){ 2 } + c: (int){ 3 } + a: (int){ 1 } + } + B: (struct){ d: (int){ 4 } + b: (int){ 2 } + c: (int){ 3 } + a: (int){ 1 } } } } -- diff/todo/p3 -- Reordering -- out/eval -- (struct){ S: (struct){ A: (struct){ a: (int){ 1 } } B: (struct){ a: (int){ 1 } b: (int){ 2 } } } T: (struct){ A: (struct){ a: (int){ 1 } c: (int){ 3 } } B: (struct){ a: (int){ 1 } c: (int){ 3 } b: (int){ 2 } d: (int){ 4 } } } } cue-lang-cue-db9cc73/cue/testdata/resolve/044_field_templates.txtar000066400000000000000000000040611474664451600253610ustar00rootroot00000000000000#name: field templates #evalPartial -- in.cue -- a: { {[name=_]: int} k: 1 } b: { {[X=_]: {x: 0, y: *1 | int}} v: {} w: {x: 0} } b: {[y=_]: {}} c: { {[Name=_]: {name: Name, y: 1}} foo: {} bar: _ } -- out/def -- a: { {[name=string]: int} k: 1 } b: { {[X=string]: { x: 0, y: *1 | int }} v: { x: 0 y: *1 | int } w: { x: 0 y: *1 | int } } c: { {[Name=string]: { y: 1, name: Name }} foo: { y: 1 name: "foo" } bar: { y: 1 name: "bar" } } -- out/export -- a: { k: 1 } b: { v: { x: 0 y: 1 } w: { x: 0 y: 1 } } c: { foo: { y: 1 name: "foo" } bar: { y: 1 name: "bar" } } -- out/yaml -- a: k: 1 b: v: x: 0 y: 1 w: x: 0 y: 1 c: foo: y: 1 name: foo bar: y: 1 name: bar -- out/json -- {"a":{"k":1},"b":{"v":{"x":0,"y":1},"w":{"x":0,"y":1}},"c":{"foo":{"y":1,"name":"foo"},"bar":{"y":1,"name":"bar"}}} -- out/legacy-debug -- <0>{a: <1>{[]: <2>(name: string)->int, k: 1}, b: <3>{[]: <4>(X: string)->(<5>{x: 0, y: (*1 | int)} & <6>{}), v: <7>{x: 0, y: (*1 | int)}, w: <8>{x: 0, y: (*1 | int)}}, c: <9>{[]: <10>(Name: string)-><11>{y: 1, name: <10>.Name}, foo: <12>{y: 1, name: "foo"}, bar: <13>{y: 1, name: "bar"}}} -- out/compile -- --- in.cue { a: { { [_]: int } k: 1 } b: { { [_]: { x: 0 y: (*1|int) } } v: {} w: { x: 0 } } b: { [_]: {} } c: { { [_]: { name: 〈1;-〉 y: 1 } } foo: {} bar: _ } } -- out/eval/stats -- Leaks: 0 Freed: 21 Reused: 15 Allocs: 6 Retain: 0 Unifications: 17 Conjuncts: 33 Disjuncts: 21 -- out/eval -- (struct){ a: (struct){ k: (int){ 1 } } b: (struct){ v: (struct){ x: (int){ 0 } y: (int){ |(*(int){ 1 }, (int){ int }) } } w: (struct){ x: (int){ 0 } y: (int){ |(*(int){ 1 }, (int){ int }) } } } c: (struct){ foo: (struct){ name: (string){ "foo" } y: (int){ 1 } } bar: (struct){ name: (string){ "bar" } y: (int){ 1 } } } } cue-lang-cue-db9cc73/cue/testdata/resolve/045_range_unification.txtar000066400000000000000000000262601474664451600257120ustar00rootroot00000000000000#name: range unification #evalPartial -- in.cue -- // with concrete values a1: >=1 & <=5 & 3 a2: >=1 & <=5 & 1 a3: >=1 & <=5 & 5 a4: >=1 & <=5 & 6 a5: >=1 & <=5 & 0 a6: 3 & >=1 & <=5 a7: 1 & >=1 & <=5 a8: 5 & >=1 & <=5 a9: 6 & >=1 & <=5 a10: 0 & >=1 & <=5 // with ranges b1: >=1 & <=5 & >=1 & <=5 b2: >=1 & <=5 & >=1 & <=1 b3: >=1 & <=5 & >=5 & <=5 b4: >=1 & <=5 & >=2 & <=3 b5: >=1 & <=5 & >=3 & <=9 b6: >=1 & <=5 & >=5 & <=9 b7: >=1 & <=5 & >=6 & <=9 b8: >=1 & <=5 & >=1 & <=5 b9: >=1 & <=1 & >=1 & <=5 b10: >=5 & <=5 & >=1 & <=5 b11: >=2 & <=3 & >=1 & <=5 b12: >=3 & <=9 & >=1 & <=5 b13: >=5 & <=9 & >=1 & <=5 b14: >=6 & <=9 & >=1 & <=5 // ranges with more general types c1: int & >=1 & <=5 c2: >=1 & <=5 & int c3: string & >=1 & <=5 c4: >=1 & <=5 & string // other types s1: >="d" & <="z" & "e" s2: >="d" & <="z" & "ee" n1: number & >=1 & <=2 n2: int & >=1.1 & <=1.3 n3: >=1.0 & <=3.0 & 2 n4: >=0.0 & <=0.1 & 0.09999 n5: >=1 & <=5 & 2.5 -- out/def -- // with concrete values a1: 3 a2: 1 a3: 5 a4: _|_ // invalid value 6 (out of bound <=5) a5: _|_ // invalid value 0 (out of bound >=1) a6: 3 a7: 1 a8: 5 a9: _|_ // invalid value 6 (out of bound <=5) a10: _|_ // invalid value 0 (out of bound >=1) // with ranges b1: >=1 & <=5 b2: 1 b3: 5 b4: >=2 & <=3 b5: >=3 & <=5 b6: 5 b7: _|_ // conflicting bounds >=6 and <=5 b8: >=1 & <=5 b9: 1 b10: 5 b11: >=2 & <=3 b12: >=3 & <=5 b13: 5 b14: _|_ // conflicting bounds >=6 and <=5 // ranges with more general types c1: uint & >=1 & <=5 c2: uint & >=1 & <=5 c3: _|_ // conflicting values string and >=1 (mismatched types string and number) c4: _|_ // conflicting values (>=1 & <=5) and string (mismatched types number and string) // other types s1: "e" s2: "ee" n1: >=1 & <=2 n2: _|_ // conflicting bounds int & >=1.1 and <=1.3 n3: 2 n4: 0.09999 n5: 2.5 -- out/legacy-debug -- <0>{a1: 3, a2: 1, a3: 5, a4: _|_((<=5 & 6):invalid value 6 (out of bound <=5)), a5: _|_((>=1 & 0):invalid value 0 (out of bound >=1)), a6: 3, a7: 1, a8: 5, a9: _|_((<=5 & 6):invalid value 6 (out of bound <=5)), a10: _|_((>=1 & 0):invalid value 0 (out of bound >=1)), b1: (>=1 & <=5), b2: 1, b3: 5, b4: (>=2 & <=3), b5: (>=3 & <=5), b6: 5, b7: _|_(conflicting bounds >=6 and <=5), b8: (>=1 & <=5), b9: 1, b10: 5, b11: (>=2 & <=3), b12: (>=3 & <=5), b13: 5, b14: _|_(conflicting bounds >=6 and <=5), c1: (int & >=1 & <=5), c2: (<=5 & int & >=1), c3: _|_((string & >=1):conflicting values string and >=1 (mismatched types string and number)), c4: _|_(((>=1 & <=5) & string):conflicting values (>=1 & <=5) and string (mismatched types number and string)), s1: "e", s2: "ee", n1: (>=1 & <=2), n2: _|_(conflicting bounds int & >=1.1 and <=1.3), n3: 2, n4: 0.09999, n5: 2.5} -- out/compile -- --- in.cue { a1: ((>=1 & <=5) & 3) a2: ((>=1 & <=5) & 1) a3: ((>=1 & <=5) & 5) a4: ((>=1 & <=5) & 6) a5: ((>=1 & <=5) & 0) a6: ((3 & >=1) & <=5) a7: ((1 & >=1) & <=5) a8: ((5 & >=1) & <=5) a9: ((6 & >=1) & <=5) a10: ((0 & >=1) & <=5) b1: (((>=1 & <=5) & >=1) & <=5) b2: (((>=1 & <=5) & >=1) & <=1) b3: (((>=1 & <=5) & >=5) & <=5) b4: (((>=1 & <=5) & >=2) & <=3) b5: (((>=1 & <=5) & >=3) & <=9) b6: (((>=1 & <=5) & >=5) & <=9) b7: (((>=1 & <=5) & >=6) & <=9) b8: (((>=1 & <=5) & >=1) & <=5) b9: (((>=1 & <=1) & >=1) & <=5) b10: (((>=5 & <=5) & >=1) & <=5) b11: (((>=2 & <=3) & >=1) & <=5) b12: (((>=3 & <=9) & >=1) & <=5) b13: (((>=5 & <=9) & >=1) & <=5) b14: (((>=6 & <=9) & >=1) & <=5) c1: ((int & >=1) & <=5) c2: ((>=1 & <=5) & int) c3: ((string & >=1) & <=5) c4: ((>=1 & <=5) & string) s1: ((>="d" & <="z") & "e") s2: ((>="d" & <="z") & "ee") n1: ((number & >=1) & <=2) n2: ((int & >=1.1) & <=1.3) n3: ((>=1.0 & <=3.0) & 2) n4: ((>=0.0 & <=0.1) & 0.09999) n5: ((>=1 & <=5) & 2.5) } -- out/eval/stats -- Leaks: 0 Freed: 36 Reused: 34 Allocs: 2 Retain: 0 Unifications: 36 Conjuncts: 120 Disjuncts: 36 -- out/evalalpha -- Errors: c3: conflicting values string and >=1 (mismatched types string and number): ./in.cue:34:5 ./in.cue:34:14 c4: conflicting values string and >=1 (mismatched types string and number): ./in.cue:35:5 ./in.cue:35:17 a4: invalid value 6 (out of bound <=5): ./in.cue:5:11 ./in.cue:5:17 a5: invalid value 0 (out of bound >=1): ./in.cue:6:5 ./in.cue:6:17 a9: invalid value 6 (out of bound <=5): ./in.cue:11:16 ./in.cue:11:6 a10: invalid value 0 (out of bound >=1): ./in.cue:12:10 ./in.cue:12:6 b7: incompatible number bounds <=5 and >=6: ./in.cue:21:17 ./in.cue:21:11 b14: incompatible number bounds <=5 and >=6: ./in.cue:29:24 ./in.cue:29:6 n2: incompatible integer bounds <=1.3 and >=1.1: ./in.cue:42:19 ./in.cue:42:11 Result: (_|_){ // [eval] a1: (int){ 3 } a2: (int){ 1 } a3: (int){ 5 } a4: (_|_){ // [eval] a4: invalid value 6 (out of bound <=5): // ./in.cue:5:11 // ./in.cue:5:17 } a5: (_|_){ // [eval] a5: invalid value 0 (out of bound >=1): // ./in.cue:6:5 // ./in.cue:6:17 } a6: (int){ 3 } a7: (int){ 1 } a8: (int){ 5 } a9: (_|_){ // [eval] a9: invalid value 6 (out of bound <=5): // ./in.cue:11:16 // ./in.cue:11:6 } a10: (_|_){ // [eval] a10: invalid value 0 (out of bound >=1): // ./in.cue:12:10 // ./in.cue:12:6 } b1: (number){ &(>=1, <=5) } b2: (number){ 1 } b3: (number){ 5 } b4: (number){ &(>=2, <=3) } b5: (number){ &(>=3, <=5) } b6: (number){ 5 } b7: (_|_){ // [eval] b7: incompatible number bounds <=5 and >=6: // ./in.cue:21:17 // ./in.cue:21:11 } b8: (number){ &(>=1, <=5) } b9: (number){ 1 } b10: (number){ 5 } b11: (number){ &(>=2, <=3) } b12: (number){ &(>=3, <=5) } b13: (number){ 5 } b14: (_|_){ // [eval] b14: incompatible number bounds <=5 and >=6: // ./in.cue:29:24 // ./in.cue:29:6 } c1: (int){ &(>=1, <=5, int) } c2: (int){ &(>=1, <=5, int) } c3: (_|_){ // [eval] c3: conflicting values string and >=1 (mismatched types string and number): // ./in.cue:34:5 // ./in.cue:34:14 } c4: (_|_){ // [eval] c4: conflicting values string and >=1 (mismatched types string and number): // ./in.cue:35:5 // ./in.cue:35:17 } s1: (string){ "e" } s2: (string){ "ee" } n1: (number){ &(>=1, <=2) } n2: (_|_){ // [eval] n2: incompatible integer bounds <=1.3 and >=1.1: // ./in.cue:42:19 // ./in.cue:42:11 } n3: (int){ 2 } n4: (float){ 0.09999 } n5: (float){ 2.5 } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,19 +1,10 @@ Errors: -b14: incompatible number bounds <=5 and >=6: - ./in.cue:29:6 - ./in.cue:29:24 -b7: incompatible number bounds <=5 and >=6: - ./in.cue:21:11 - ./in.cue:21:17 c3: conflicting values string and >=1 (mismatched types string and number): ./in.cue:34:5 ./in.cue:34:14 -c4: conflicting values >=1 and string (mismatched types number and string): +c4: conflicting values string and >=1 (mismatched types string and number): ./in.cue:35:5 ./in.cue:35:17 -n2: incompatible integer bounds <=1.3 and >=1.1: - ./in.cue:42:11 - ./in.cue:42:19 a4: invalid value 6 (out of bound <=5): ./in.cue:5:11 ./in.cue:5:17 @@ -26,6 +17,15 @@ a10: invalid value 0 (out of bound >=1): ./in.cue:12:10 ./in.cue:12:6 +b7: incompatible number bounds <=5 and >=6: + ./in.cue:21:17 + ./in.cue:21:11 +b14: incompatible number bounds <=5 and >=6: + ./in.cue:29:24 + ./in.cue:29:6 +n2: incompatible integer bounds <=1.3 and >=1.1: + ./in.cue:42:19 + ./in.cue:42:11 Result: (_|_){ @@ -64,8 +64,8 @@ b6: (number){ 5 } b7: (_|_){ // [eval] b7: incompatible number bounds <=5 and >=6: - // ./in.cue:21:11 // ./in.cue:21:17 + // ./in.cue:21:11 } b8: (number){ &(>=1, <=5) } b9: (number){ 1 } @@ -75,8 +75,8 @@ b13: (number){ 5 } b14: (_|_){ // [eval] b14: incompatible number bounds <=5 and >=6: - // ./in.cue:29:6 // ./in.cue:29:24 + // ./in.cue:29:6 } c1: (int){ &(>=1, <=5, int) } c2: (int){ &(>=1, <=5, int) } @@ -86,7 +86,7 @@ // ./in.cue:34:14 } c4: (_|_){ - // [eval] c4: conflicting values >=1 and string (mismatched types number and string): + // [eval] c4: conflicting values string and >=1 (mismatched types string and number): // ./in.cue:35:5 // ./in.cue:35:17 } @@ -95,8 +95,8 @@ n1: (number){ &(>=1, <=2) } n2: (_|_){ // [eval] n2: incompatible integer bounds <=1.3 and >=1.1: - // ./in.cue:42:11 // ./in.cue:42:19 + // ./in.cue:42:11 } n3: (int){ 2 } n4: (float){ 0.09999 } -- diff/todo/p3 -- Reordering of error messages. -- out/eval -- Errors: b14: incompatible number bounds <=5 and >=6: ./in.cue:29:6 ./in.cue:29:24 b7: incompatible number bounds <=5 and >=6: ./in.cue:21:11 ./in.cue:21:17 c3: conflicting values string and >=1 (mismatched types string and number): ./in.cue:34:5 ./in.cue:34:14 c4: conflicting values >=1 and string (mismatched types number and string): ./in.cue:35:5 ./in.cue:35:17 n2: incompatible integer bounds <=1.3 and >=1.1: ./in.cue:42:11 ./in.cue:42:19 a4: invalid value 6 (out of bound <=5): ./in.cue:5:11 ./in.cue:5:17 a5: invalid value 0 (out of bound >=1): ./in.cue:6:5 ./in.cue:6:17 a9: invalid value 6 (out of bound <=5): ./in.cue:11:16 ./in.cue:11:6 a10: invalid value 0 (out of bound >=1): ./in.cue:12:10 ./in.cue:12:6 Result: (_|_){ // [eval] a1: (int){ 3 } a2: (int){ 1 } a3: (int){ 5 } a4: (_|_){ // [eval] a4: invalid value 6 (out of bound <=5): // ./in.cue:5:11 // ./in.cue:5:17 } a5: (_|_){ // [eval] a5: invalid value 0 (out of bound >=1): // ./in.cue:6:5 // ./in.cue:6:17 } a6: (int){ 3 } a7: (int){ 1 } a8: (int){ 5 } a9: (_|_){ // [eval] a9: invalid value 6 (out of bound <=5): // ./in.cue:11:16 // ./in.cue:11:6 } a10: (_|_){ // [eval] a10: invalid value 0 (out of bound >=1): // ./in.cue:12:10 // ./in.cue:12:6 } b1: (number){ &(>=1, <=5) } b2: (number){ 1 } b3: (number){ 5 } b4: (number){ &(>=2, <=3) } b5: (number){ &(>=3, <=5) } b6: (number){ 5 } b7: (_|_){ // [eval] b7: incompatible number bounds <=5 and >=6: // ./in.cue:21:11 // ./in.cue:21:17 } b8: (number){ &(>=1, <=5) } b9: (number){ 1 } b10: (number){ 5 } b11: (number){ &(>=2, <=3) } b12: (number){ &(>=3, <=5) } b13: (number){ 5 } b14: (_|_){ // [eval] b14: incompatible number bounds <=5 and >=6: // ./in.cue:29:6 // ./in.cue:29:24 } c1: (int){ &(>=1, <=5, int) } c2: (int){ &(>=1, <=5, int) } c3: (_|_){ // [eval] c3: conflicting values string and >=1 (mismatched types string and number): // ./in.cue:34:5 // ./in.cue:34:14 } c4: (_|_){ // [eval] c4: conflicting values >=1 and string (mismatched types number and string): // ./in.cue:35:5 // ./in.cue:35:17 } s1: (string){ "e" } s2: (string){ "ee" } n1: (number){ &(>=1, <=2) } n2: (_|_){ // [eval] n2: incompatible integer bounds <=1.3 and >=1.1: // ./in.cue:42:11 // ./in.cue:42:19 } n3: (int){ 2 } n4: (float){ 0.09999 } n5: (float){ 2.5 } } cue-lang-cue-db9cc73/cue/testdata/resolve/046_predefined_ranges.txtar000066400000000000000000000016501474664451600256670ustar00rootroot00000000000000#name: predefined ranges #evalPartial -- in.cue -- k1: int8 k1: 44 k2: int64 k2: -8_000_000_000 e1: int16 e1: 100_000 -- out/def -- k1: 44 k2: -8000000000 e1: _|_ // invalid value 100000 (out of bound int & <=32767) -- out/legacy-debug -- <0>{k1: 44, k2: -8000000000, e1: _|_((int & <=32767 & 100000):invalid value 100000 (out of bound int & <=32767))} -- out/compile -- --- in.cue { k1: &(int, >=-128, <=127) k1: 44 k2: &(int, >=-9223372036854775808, <=9223372036854775807) k2: -8000000000 e1: &(int, >=-32768, <=32767) e1: 100000 } -- out/eval/stats -- Leaks: 0 Freed: 4 Reused: 2 Allocs: 2 Retain: 0 Unifications: 4 Conjuncts: 7 Disjuncts: 4 -- out/eval -- Errors: e1: invalid value 100000 (out of bound <=32767): ./in.cue:8:5 Result: (_|_){ // [eval] k1: (int){ 44 } k2: (int){ -8000000000 } e1: (_|_){ // [eval] e1: invalid value 100000 (out of bound <=32767): // ./in.cue:8:5 } } cue-lang-cue-db9cc73/cue/testdata/resolve/047_struct_comprehensions.txtar000066400000000000000000000025311474664451600266630ustar00rootroot00000000000000#name: struct comprehensions #evalPartial -- in.cue -- obj: foo: a: "bar" obj: [Name=string]: { a: *"dummy" | string if true { sub: as: a } } for k, v in {#def: 1, opt?: 2, _hid: 3, reg: 4} { "\(k)": v } -- out/def -- obj: { {[Name=string]: { a: *"dummy" | string, sub: { as: a } }} foo: { a: "bar" sub: { as: "bar" } } } reg: 4 -- out/export -- obj: { foo: { a: "bar" sub: { as: "bar" } } } reg: 4 -- out/yaml -- obj: foo: a: bar sub: as: bar reg: 4 -- out/json -- {"obj":{"foo":{"a":"bar","sub":{"as":"bar"}}},"reg":4} -- out/legacy-debug -- <0>{obj: <1>{[]: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield <4>{sub: <5>{as: <3>.a}}}, foo: <6>{a: "bar", sub: <7>{as: "bar"}}}, reg: 4} -- out/compile -- --- in.cue { obj: { foo: { a: "bar" } } obj: { [string]: { a: (*"dummy"|string) if true { sub: { as: 〈2;a〉 } } } } for k, v in { #def: 1 opt?: 2 _hid: 3 reg: 4 } { "\(〈1;k〉)": 〈1;v〉 } } -- out/eval/stats -- Leaks: 2 Freed: 12 Reused: 7 Allocs: 7 Retain: 2 Unifications: 10 Conjuncts: 19 Disjuncts: 13 -- out/eval -- (struct){ obj: (struct){ foo: (struct){ a: (string){ "bar" } sub: (struct){ as: (string){ "bar" } } } } reg: (int){ 4 } } cue-lang-cue-db9cc73/cue/testdata/resolve/048_builtins.txtar000066400000000000000000000300261474664451600240550ustar00rootroot00000000000000#name: builtins #evalPartial -- in.cue -- import ( "list" "strings" ) a1: { a: and([b, c]) b: =~"oo" c: =~"fo" } a2: a1 & {a: "foo"} a3: a1 & {a: "bar"} o1: { a: or([b, c]) b: string c: "bar" } o2: o1 & {a: "foo"} o3: o1 & {a: "foo", b: "baz"} // Issue #585 stringListErrors: { a: { x: [string, ...string] result: strings.Join(x, " ") } b: { x: [int, ...string] result: strings.Join(x, " ") } c: { x: [] result: strings.Join(x, int) } } decimalListErrors: { a: { x: [string] result: list.Avg(x) } b: { x: [int, ...string] result: list.Avg(x) } } -- issue3648.cue -- // Fully finalize values before passing them to builtins. import "list" issue3648: reduced: { [string]: { a: list.Concat([b]) b: [{}] } foo: {} } issue3648: full: { #Redirect: path?: string [string]: { // Note that this bug disappears if the order of the fields below is swapped. allRedirects: list.Concat([redirects]) redirects: [...#Redirect] } foo: {} } -- out/def -- a1: { a: =~"oo" & =~"fo" b: =~"oo" c: =~"fo" } a2: a1 & { a: "foo" } a3: a1 & { a: "bar" } o1: { a: string b: string c: "bar" } o2: o1 & { a: "foo" } o3: o1 & { a: "foo" b: "baz" } -- out/legacy-debug -- <0>{a1: <1>{a: (=~"oo" & =~"fo"), b: =~"oo", c: =~"fo"}, a2: <2>{a: "foo", b: =~"oo", c: =~"fo"}, a3: <3>{a: _|_((=~"oo" & "bar"):invalid value "bar" (does not match =~"oo")), b: =~"oo", c: =~"fo"}, o1: <4>{a: string, b: string, c: "bar"}, o2: <5>{a: "foo", b: string, c: "bar"}, o3: <6>{a: _|_(("baz" & "foo"):empty disjunction: conflicting values "baz" and "foo";("bar" & "foo"):empty disjunction: conflicting values "bar" and "foo"), b: "baz", c: "bar"}} -- out/eval/stats -- Leaks: 6 Freed: 79 Reused: 70 Allocs: 15 Retain: 26 Unifications: 73 Conjuncts: 152 Disjuncts: 97 -- out/evalalpha -- Errors: o3.a: 2 errors in empty disjunction: o3.a: conflicting values "bar" and "foo": ./in.cue:17:5 ./in.cue:20:14 o3.a: conflicting values "baz" and "foo": ./in.cue:20:14 ./in.cue:20:24 a3.a: invalid value "bar" (out of bound =~"oo"): ./in.cue:8:5 ./in.cue:7:5 ./in.cue:12:14 a3.a: invalid value "bar" (out of bound =~"fo"): ./in.cue:9:5 ./in.cue:7:5 ./in.cue:12:14 stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string: ./in.cue:31:11 ./in.cue:30:7 stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join: ./in.cue:36:27 decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number: ./in.cue:43:11 ./in.cue:42:7 Result: (_|_){ // [eval] a1: (struct){ a: (string){ &(=~"oo", =~"fo") } b: (string){ =~"oo" } c: (string){ =~"fo" } } a2: (struct){ a: (string){ "foo" } b: (string){ =~"oo" } c: (string){ =~"fo" } } a3: (_|_){ // [eval] a: (_|_){ // [eval] a3.a: invalid value "bar" (out of bound =~"oo"): // ./in.cue:8:5 // ./in.cue:7:5 // ./in.cue:12:14 // a3.a: invalid value "bar" (out of bound =~"fo"): // ./in.cue:9:5 // ./in.cue:7:5 // ./in.cue:12:14 } b: (string){ =~"oo" } c: (string){ =~"fo" } } o1: (struct){ a: (string){ |((string){ string }, (string){ "bar" }) } b: (string){ string } c: (string){ "bar" } } o2: (struct){ a: (string){ "foo" } b: (string){ string } c: (string){ "bar" } } o3: (_|_){ // [eval] a: (_|_){ // [eval] o3.a: 2 errors in empty disjunction: // o3.a: conflicting values "bar" and "foo": // ./in.cue:17:5 // ./in.cue:20:14 // o3.a: conflicting values "baz" and "foo": // ./in.cue:20:14 // ./in.cue:20:24 } b: (string){ "baz" } c: (string){ "bar" } } stringListErrors: (_|_){ // [eval] a: (struct){ x: (list){ 0: (string){ string } } result: (_|_){ // [incomplete] stringListErrors.a.result: non-concrete value string for element 0 of string list argument 0: // ./in.cue:26:11 // ./in.cue:25:7 } } b: (_|_){ // [eval] x: (list){ 0: (int){ int } } result: (_|_){ // [eval] stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string: // ./in.cue:31:11 // ./in.cue:30:7 } } c: (_|_){ // [eval] x: (#list){ } result: (_|_){ // [eval] stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join: // ./in.cue:36:27 } } } decimalListErrors: (_|_){ // [eval] a: (_|_){ // [eval] x: (#list){ 0: (string){ string } } result: (_|_){ // [eval] decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number: // ./in.cue:43:11 // ./in.cue:42:7 } } b: (struct){ x: (list){ 0: (int){ int } } result: (_|_){ // [incomplete] decimalListErrors.b.result: non-concrete value int for element 0 of number list argument 0: // ./in.cue:48:11 // ./in.cue:47:7 } } } issue3648: (struct){ reduced: (struct){ foo: (struct){ a: (#list){ 0: (struct){ } } b: (#list){ 0: (struct){ } } } } full: (struct){ #Redirect: (#struct){ path?: (string){ string } } foo: (struct){ allRedirects: (#list){ } redirects: (list){ } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,13 +1,9 @@ Errors: o3.a: 2 errors in empty disjunction: o3.a: conflicting values "bar" and "foo": - ./in.cue:15:12 ./in.cue:17:5 - ./in.cue:20:5 ./in.cue:20:14 o3.a: conflicting values "baz" and "foo": - ./in.cue:15:9 - ./in.cue:20:5 ./in.cue:20:14 ./in.cue:20:24 a3.a: invalid value "bar" (out of bound =~"oo"): @@ -70,13 +66,9 @@ a: (_|_){ // [eval] o3.a: 2 errors in empty disjunction: // o3.a: conflicting values "bar" and "foo": - // ./in.cue:15:12 // ./in.cue:17:5 - // ./in.cue:20:5 // ./in.cue:20:14 // o3.a: conflicting values "baz" and "foo": - // ./in.cue:15:9 - // ./in.cue:20:5 // ./in.cue:20:14 // ./in.cue:20:24 } -- diff/todo/p2 -- Missing error positions. -- out/eval -- Errors: o3.a: 2 errors in empty disjunction: o3.a: conflicting values "bar" and "foo": ./in.cue:15:12 ./in.cue:17:5 ./in.cue:20:5 ./in.cue:20:14 o3.a: conflicting values "baz" and "foo": ./in.cue:15:9 ./in.cue:20:5 ./in.cue:20:14 ./in.cue:20:24 a3.a: invalid value "bar" (out of bound =~"oo"): ./in.cue:8:5 ./in.cue:7:5 ./in.cue:12:14 a3.a: invalid value "bar" (out of bound =~"fo"): ./in.cue:9:5 ./in.cue:7:5 ./in.cue:12:14 stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string: ./in.cue:31:11 ./in.cue:30:7 stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join: ./in.cue:36:27 decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number: ./in.cue:43:11 ./in.cue:42:7 Result: (_|_){ // [eval] a1: (struct){ a: (string){ &(=~"oo", =~"fo") } b: (string){ =~"oo" } c: (string){ =~"fo" } } a2: (struct){ a: (string){ "foo" } b: (string){ =~"oo" } c: (string){ =~"fo" } } a3: (_|_){ // [eval] a: (_|_){ // [eval] a3.a: invalid value "bar" (out of bound =~"oo"): // ./in.cue:8:5 // ./in.cue:7:5 // ./in.cue:12:14 // a3.a: invalid value "bar" (out of bound =~"fo"): // ./in.cue:9:5 // ./in.cue:7:5 // ./in.cue:12:14 } b: (string){ =~"oo" } c: (string){ =~"fo" } } o1: (struct){ a: (string){ |((string){ string }, (string){ "bar" }) } b: (string){ string } c: (string){ "bar" } } o2: (struct){ a: (string){ "foo" } b: (string){ string } c: (string){ "bar" } } o3: (_|_){ // [eval] a: (_|_){ // [eval] o3.a: 2 errors in empty disjunction: // o3.a: conflicting values "bar" and "foo": // ./in.cue:15:12 // ./in.cue:17:5 // ./in.cue:20:5 // ./in.cue:20:14 // o3.a: conflicting values "baz" and "foo": // ./in.cue:15:9 // ./in.cue:20:5 // ./in.cue:20:14 // ./in.cue:20:24 } b: (string){ "baz" } c: (string){ "bar" } } stringListErrors: (_|_){ // [eval] a: (struct){ x: (list){ 0: (string){ string } } result: (_|_){ // [incomplete] stringListErrors.a.result: non-concrete value string for element 0 of string list argument 0: // ./in.cue:26:11 // ./in.cue:25:7 } } b: (_|_){ // [eval] x: (list){ 0: (int){ int } } result: (_|_){ // [eval] stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string: // ./in.cue:31:11 // ./in.cue:30:7 } } c: (_|_){ // [eval] x: (#list){ } result: (_|_){ // [eval] stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join: // ./in.cue:36:27 } } } decimalListErrors: (_|_){ // [eval] a: (_|_){ // [eval] x: (#list){ 0: (string){ string } } result: (_|_){ // [eval] decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number: // ./in.cue:43:11 // ./in.cue:42:7 } } b: (struct){ x: (list){ 0: (int){ int } } result: (_|_){ // [incomplete] decimalListErrors.b.result: non-concrete value int for element 0 of number list argument 0: // ./in.cue:48:11 // ./in.cue:47:7 } } } issue3648: (struct){ reduced: (struct){ foo: (struct){ a: (#list){ 0: (struct){ } } b: (#list){ 0: (struct){ } } } } full: (struct){ #Redirect: (#struct){ path?: (string){ string } } foo: (struct){ allRedirects: (#list){ } redirects: (list){ } } } } } -- out/compile -- --- in.cue { a1: { a: and([ 〈1;b〉, 〈1;c〉, ]) b: =~"oo" c: =~"fo" } a2: (〈0;a1〉 & { a: "foo" }) a3: (〈0;a1〉 & { a: "bar" }) o1: { a: or([ 〈1;b〉, 〈1;c〉, ]) b: string c: "bar" } o2: (〈0;o1〉 & { a: "foo" }) o3: (〈0;o1〉 & { a: "foo" b: "baz" }) stringListErrors: { a: { x: [ string, ...string, ] result: 〈import;strings〉.Join(〈0;x〉, " ") } b: { x: [ int, ...string, ] result: 〈import;strings〉.Join(〈0;x〉, " ") } c: { x: [] result: 〈import;strings〉.Join(〈0;x〉, int) } } decimalListErrors: { a: { x: [ string, ] result: 〈import;list〉.Avg(〈0;x〉) } b: { x: [ int, ...string, ] result: 〈import;list〉.Avg(〈0;x〉) } } } --- issue3648.cue { issue3648: { reduced: { [string]: { a: 〈import;list〉.Concat([ 〈1;b〉, ]) b: [ {}, ] } foo: {} } } issue3648: { full: { #Redirect: { path?: string } [string]: { allRedirects: 〈import;list〉.Concat([ 〈1;redirects〉, ]) redirects: [ ...〈2;#Redirect〉, ] } foo: {} } } } cue-lang-cue-db9cc73/cue/testdata/scalars/000077500000000000000000000000001474664451600205155ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/testdata/scalars/embed.txtar000066400000000000000000000353661474664451600226720ustar00rootroot00000000000000// Issue ##739 -- in.cue -- import "strings" import "list" intEmbed: { a1: { 2 } a2: { v: { 3 #foo: a2.v + 1 } w: v x: v.#foo } a3: a1 + a2.v } listEmbed: { a1: { 2 } b3: { [1, 2] #foo: 1 } b4: list.Concat([b3, b3]) b5: b3[1] b6: b3[5] b7: b4[a1] // 1 } stringEmbed: { s1: { "foo" #bar: "bar" } s2: [ s1, {s1.#bar, #baz: 4}] s3: strings.Join(s2, "--") } outPattern: { sum: { out: #a + #b #a: int #b: int } used: sum & {#a: 1, #b: 3} } arithmetic: { sum: { #a + #b #a: int #b: int } a1: (sum & {_, #a: 1, #b: 3}) + 2 a2: 2 + (sum & {_, #a: 1, #b: 3}) a3: 2 + (2 + (sum & {_, #a: 1, #b: 3})) } defCheck: { a: { #def: 1 } b: a.#def } optionalExists: { string | { value?: string if value != _|_ { other: int } } } optionalCheck: { thing: string | { value?: string if value != _|_ { other: int } } thing: { value: "some string" other: 3 } } hidden: { issue794: { _foo: "foo" [_foo] } } -- issue2113.cue -- // In all these tests, embedded scalars should resolve without error. merged: t1: p1: { #fn: { #in2: _, _ } #fn: { #in2: c1: string, #in2.c1 } x: #fn & {#in2: {c1: "V 1"}, _} } merged: t1: p2: { #fn: { #in2: c1: string, #in2.c1 } #fn: { #in2: _, _ } x: #fn & {#in2: {c1: "V 1"}, _} } merged: t1: p3: { x: #fn & {#in2: {c1: "V 1"}, _} #fn: { #in2: c1: string, #in2.c1 } #fn: { #in2: _, _ } } merged: t2: p1: { #fn: { #in2: {}, _ } #fn: { #in2: c1: string, #in2.c1 } x: #fn & {#in2: {c1: "V 1"}, _} } merged: t2: p2: { #fn: { #in2: c1: string, #in2.c1 } #fn: { #in2: {}, _ } x: #fn & {#in2: {c1: "V 1"}, _} } merged: t2: p3: { x: #fn & {#in2: {c1: "V 1"}, _} #fn: { #in2: c1: string, #in2.c1 } #fn: { #in2: {}, _ } } -- issue2163.cue -- selfRefInEmbed: t1: { #Func: { #in: _ _ } #fn: #Func #fn: { #in: _ (#Func & { _foo: #in "buzz" }) + "fiz" } } -- out/eval/stats -- Leaks: 10 Freed: 130 Reused: 123 Allocs: 17 Retain: 57 Unifications: 136 Conjuncts: 304 Disjuncts: 173 -- out/evalalpha -- Errors: listEmbed.b6: index out of range [5] with length 2: ./in.cue:29:9 Result: (_|_){ // [eval] intEmbed: (struct){ a1: (int){ 2 } a2: (struct){ v: (int){ 3 #foo: (int){ 4 } } w: ~(intEmbed.a2.v) x: (int){ 4 } } a3: (int){ 5 } } listEmbed: (_|_){ // [eval] a1: (int){ 2 } b3: (#list){ #foo: (int){ 1 } 0: (int){ 1 } 1: (int){ 2 } } b4: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 1 } 3: (int){ 2 } } b5: (int){ 2 } b6: (_|_){ // [eval] listEmbed.b6: index out of range [5] with length 2: // ./in.cue:29:9 } b7: (int){ 1 } } stringEmbed: (struct){ s1: (string){ "foo" #bar: (string){ "bar" } } s2: (#list){ 0: ~(stringEmbed.s1) 1: (string){ "bar" #baz: (int){ 4 } } } s3: (string){ "foo--bar" } } outPattern: (struct){ sum: (struct){ out: (_|_){ // [incomplete] outPattern.sum.out: non-concrete value int in operand to +: // ./in.cue:44:8 // ./in.cue:45:8 } #a: (int){ int } #b: (int){ int } } used: (struct){ #a: (int){ 1 } #b: (int){ 3 } out: (int){ 4 } } } arithmetic: (struct){ sum: (_|_){ // [incomplete] arithmetic.sum: non-concrete value int in operand to +: // ./in.cue:53:3 // ./in.cue:54:7 #a: (int){ int } #b: (int){ int } } a1: (int){ 6 } a2: (int){ 6 } a3: (int){ 8 } } defCheck: (struct){ a: (struct){ #def: (int){ 1 } } b: (int){ 1 } } optionalExists: ((string|struct)){ |((string){ string }, (struct){ value?: (string){ string } }) } optionalCheck: (struct){ thing: (struct){ value: (string){ "some string" } other: (int){ 3 } } } hidden: (struct){ issue794: (#list){ _foo: (string){ "foo" } 0: (string){ "foo" } } } merged: (struct){ t1: (struct){ p1: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p2: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p3: (struct){ x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } } } t2: (struct){ p1: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p2: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p3: (struct){ x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } } } } selfRefInEmbed: (struct){ t1: (struct){ #Func: (_){ _ #in: (_){ _ } } #fn: (string){ "buzzfiz" #in: (_){ _ } } } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,5 +1,5 @@ Errors: -listEmbed.b6: invalid list index 5 (out of bounds): +listEmbed.b6: index out of range [5] with length 2: ./in.cue:29:9 Result: @@ -12,10 +12,7 @@ 3 #foo: (int){ 4 } } - w: (int){ - 3 - #foo: (int){ 4 } - } + w: ~(intEmbed.a2.v) x: (int){ 4 } } a3: (int){ 5 } @@ -36,7 +33,7 @@ } b5: (int){ 2 } b6: (_|_){ - // [eval] listEmbed.b6: invalid list index 5 (out of bounds): + // [eval] listEmbed.b6: index out of range [5] with length 2: // ./in.cue:29:9 } b7: (int){ 1 } @@ -47,10 +44,7 @@ #bar: (string){ "bar" } } s2: (#list){ - 0: (string){ - "foo" - #bar: (string){ "bar" } - } + 0: ~(stringEmbed.s1) 1: (string){ "bar" #baz: (int){ 4 } @@ -69,9 +63,9 @@ #b: (int){ int } } used: (struct){ - out: (int){ 4 } #a: (int){ 1 } #b: (int){ 3 } + out: (int){ 4 } } } arithmetic: (struct){ -- diff/todo/p3 -- Reordering. -- diff/explanation -- Improved error message. -- out/eval -- Errors: listEmbed.b6: invalid list index 5 (out of bounds): ./in.cue:29:9 Result: (_|_){ // [eval] intEmbed: (struct){ a1: (int){ 2 } a2: (struct){ v: (int){ 3 #foo: (int){ 4 } } w: (int){ 3 #foo: (int){ 4 } } x: (int){ 4 } } a3: (int){ 5 } } listEmbed: (_|_){ // [eval] a1: (int){ 2 } b3: (#list){ #foo: (int){ 1 } 0: (int){ 1 } 1: (int){ 2 } } b4: (#list){ 0: (int){ 1 } 1: (int){ 2 } 2: (int){ 1 } 3: (int){ 2 } } b5: (int){ 2 } b6: (_|_){ // [eval] listEmbed.b6: invalid list index 5 (out of bounds): // ./in.cue:29:9 } b7: (int){ 1 } } stringEmbed: (struct){ s1: (string){ "foo" #bar: (string){ "bar" } } s2: (#list){ 0: (string){ "foo" #bar: (string){ "bar" } } 1: (string){ "bar" #baz: (int){ 4 } } } s3: (string){ "foo--bar" } } outPattern: (struct){ sum: (struct){ out: (_|_){ // [incomplete] outPattern.sum.out: non-concrete value int in operand to +: // ./in.cue:44:8 // ./in.cue:45:8 } #a: (int){ int } #b: (int){ int } } used: (struct){ out: (int){ 4 } #a: (int){ 1 } #b: (int){ 3 } } } arithmetic: (struct){ sum: (_|_){ // [incomplete] arithmetic.sum: non-concrete value int in operand to +: // ./in.cue:53:3 // ./in.cue:54:7 #a: (int){ int } #b: (int){ int } } a1: (int){ 6 } a2: (int){ 6 } a3: (int){ 8 } } defCheck: (struct){ a: (struct){ #def: (int){ 1 } } b: (int){ 1 } } optionalExists: ((string|struct)){ |((string){ string }, (struct){ value?: (string){ string } }) } optionalCheck: (struct){ thing: (struct){ value: (string){ "some string" } other: (int){ 3 } } } hidden: (struct){ issue794: (#list){ _foo: (string){ "foo" } 0: (string){ "foo" } } } merged: (struct){ t1: (struct){ p1: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p2: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p3: (struct){ x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } } } t2: (struct){ p1: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p2: (struct){ #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } } p3: (struct){ x: (string){ "V 1" #in2: (#struct){ c1: (string){ "V 1" } } } #fn: (string){ string #in2: (#struct){ c1: (string){ string } } } } } } selfRefInEmbed: (struct){ t1: (struct){ #Func: (_){ _ #in: (_){ _ } } #fn: (string){ "buzzfiz" #in: (_){ _ } } } } } -- out/compile -- --- in.cue { intEmbed: { a1: { 2 } a2: { v: { 3 #foo: (〈2;a2〉.v + 1) } w: 〈0;v〉 x: 〈0;v〉.#foo } a3: (〈0;a1〉 + 〈0;a2〉.v) } listEmbed: { a1: { 2 } b3: { [ 1, 2, ] #foo: 1 } b4: 〈import;list〉.Concat([ 〈1;b3〉, 〈1;b3〉, ]) b5: 〈0;b3〉[1] b6: 〈0;b3〉[5] b7: 〈0;b4〉[〈0;a1〉] } stringEmbed: { s1: { "foo" #bar: "bar" } s2: [ 〈1;s1〉, { 〈2;s1〉.#bar #baz: 4 }, ] s3: 〈import;strings〉.Join(〈0;s2〉, "--") } outPattern: { sum: { out: (〈0;#a〉 + 〈0;#b〉) #a: int #b: int } used: (〈0;sum〉 & { #a: 1 #b: 3 }) } arithmetic: { sum: { (〈0;#a〉 + 〈0;#b〉) #a: int #b: int } a1: ((〈0;sum〉 & { _ #a: 1 #b: 3 }) + 2) a2: (2 + (〈0;sum〉 & { _ #a: 1 #b: 3 })) a3: (2 + (2 + (〈0;sum〉 & { _ #a: 1 #b: 3 }))) } defCheck: { a: { #def: 1 } b: 〈0;a〉.#def } optionalExists: { (string|{ value?: string if (〈0;value〉 != _|_(explicit error (_|_ literal) in source)) { other: int } }) } optionalCheck: { thing: (string|{ value?: string if (〈0;value〉 != _|_(explicit error (_|_ literal) in source)) { other: int } }) thing: { value: "some string" other: 3 } } hidden: { issue794: { _foo: "foo" [ 〈1;_foo〉, ] } } } --- issue2113.cue { merged: { t1: { p1: { #fn: { #in2: _ _ } #fn: { #in2: { c1: string } 〈0;#in2〉.c1 } x: (〈0;#fn〉 & { #in2: { c1: "V 1" } _ }) } } } merged: { t1: { p2: { #fn: { #in2: { c1: string } 〈0;#in2〉.c1 } #fn: { #in2: _ _ } x: (〈0;#fn〉 & { #in2: { c1: "V 1" } _ }) } } } merged: { t1: { p3: { x: (〈0;#fn〉 & { #in2: { c1: "V 1" } _ }) #fn: { #in2: { c1: string } 〈0;#in2〉.c1 } #fn: { #in2: _ _ } } } } merged: { t2: { p1: { #fn: { #in2: {} _ } #fn: { #in2: { c1: string } 〈0;#in2〉.c1 } x: (〈0;#fn〉 & { #in2: { c1: "V 1" } _ }) } } } merged: { t2: { p2: { #fn: { #in2: { c1: string } 〈0;#in2〉.c1 } #fn: { #in2: {} _ } x: (〈0;#fn〉 & { #in2: { c1: "V 1" } _ }) } } } merged: { t2: { p3: { x: (〈0;#fn〉 & { #in2: { c1: "V 1" } _ }) #fn: { #in2: { c1: string } 〈0;#in2〉.c1 } #fn: { #in2: {} _ } } } } } --- issue2163.cue { selfRefInEmbed: { t1: { #Func: { #in: _ _ } #fn: 〈0;#Func〉 #fn: { #in: _ ((〈1;#Func〉 & { _foo: 〈1;#in〉 "buzz" }) + "fiz") } } } } cue-lang-cue-db9cc73/cue/testdata/scalars/emptystruct.txtar000066400000000000000000000063041474664451600242070ustar00rootroot00000000000000// Issue #783 -- in.cue -- elipsis: { test1: { string #foo: "bar" } #Def: { ... #foo: string _ } check: test1 & #Def } bulk: { test1: { string #foo: "bar" } #Def: { [string]: int #foo: string _ } check: test1 & #Def } optional: { test1: { string #foo: "bar" } #Def: { bar?: int #foo: string _ } check: test1 & #Def } issue783: { test1: { string #foo: "bar" } test2: { hello: "world" #foo: "bar" } #Def1: { ... #foo: string } | { string #foo: string } check1a: test1 & #Def1 check1b: test2 & #Def1 #Def2: { ... #foo: string _ } check2a: test1 & #Def2 check2b: test2 & #Def2 } -- out/eval/stats -- Leaks: 0 Freed: 54 Reused: 48 Allocs: 6 Retain: 0 Unifications: 48 Conjuncts: 107 Disjuncts: 54 -- out/eval -- (struct){ elipsis: (struct){ test1: (string){ string #foo: (string){ "bar" } } #Def: (_){ _ #foo: (string){ string } } check: (string){ string #foo: (string){ "bar" } } } bulk: (struct){ test1: (string){ string #foo: (string){ "bar" } } #Def: (_){ _ #foo: (string){ string } } check: (string){ string #foo: (string){ "bar" } } } optional: (struct){ test1: (string){ string #foo: (string){ "bar" } } #Def: (_){ _ bar?: (int){ int } #foo: (string){ string } } check: (string){ string #foo: (string){ "bar" } bar?: (int){ int } } } issue783: (struct){ test1: (string){ string #foo: (string){ "bar" } } test2: (struct){ hello: (string){ "world" } #foo: (string){ "bar" } } #Def1: ((string|struct)){ |((#struct){ #foo: (string){ string } }, (string){ string #foo: (string){ string } }) } check1a: (string){ string #foo: (string){ "bar" } } check1b: (#struct){ hello: (string){ "world" } #foo: (string){ "bar" } } #Def2: (_){ _ #foo: (string){ string } } check2a: (string){ string #foo: (string){ "bar" } } check2b: (#struct){ hello: (string){ "world" } #foo: (string){ "bar" } } } } -- out/compile -- --- in.cue { elipsis: { test1: { string #foo: "bar" } #Def: { ... #foo: string _ } check: (〈0;test1〉 & 〈0;#Def〉) } bulk: { test1: { string #foo: "bar" } #Def: { [string]: int #foo: string _ } check: (〈0;test1〉 & 〈0;#Def〉) } optional: { test1: { string #foo: "bar" } #Def: { bar?: int #foo: string _ } check: (〈0;test1〉 & 〈0;#Def〉) } issue783: { test1: { string #foo: "bar" } test2: { hello: "world" #foo: "bar" } #Def1: ({ ... #foo: string }|{ string #foo: string }) check1a: (〈0;test1〉 & 〈0;#Def1〉) check1b: (〈0;test2〉 & 〈0;#Def1〉) #Def2: { ... #foo: string _ } check2a: (〈0;test1〉 & 〈0;#Def2〉) check2b: (〈0;test2〉 & 〈0;#Def2〉) } } cue-lang-cue-db9cc73/cue/testdata/scalars/yield.txtar000066400000000000000000000042411474664451600227100ustar00rootroot00000000000000// Issue #729 -- in.cue -- ifScalar: { _#cond: true if _#cond {5} } ifScalarConflict: { _#cond: true if _#cond {5} "soo" } ifScalarNested: { _#cond: true if _#cond {{{5}}} } -- out/eval/stats -- Leaks: 0 Freed: 7 Reused: 4 Allocs: 3 Retain: 3 Unifications: 7 Conjuncts: 13 Disjuncts: 7 -- out/evalalpha -- Errors: ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): ./in.cue:10:13 ./in.cue:12:2 Result: (_|_){ // [eval] ifScalar: (int){ 5 _#cond: (bool){ true } } ifScalarConflict: (_|_){ // [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): // ./in.cue:10:13 // ./in.cue:12:2 _#cond: (bool){ true } } ifScalarNested: (int){ 5 _#cond: (bool){ true } } } -- diff/-out/evalalpha<==>+out/eval -- diff old new --- old +++ new @@ -1,6 +1,5 @@ Errors: ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): - ./in.cue:10:2 ./in.cue:10:13 ./in.cue:12:2 @@ -13,7 +12,6 @@ } ifScalarConflict: (_|_){ // [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): - // ./in.cue:10:2 // ./in.cue:10:13 // ./in.cue:12:2 _#cond: (bool){ true } -- diff/todo/p2 -- Missing error positions -- out/eval -- Errors: ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): ./in.cue:10:2 ./in.cue:10:13 ./in.cue:12:2 Result: (_|_){ // [eval] ifScalar: (int){ 5 _#cond: (bool){ true } } ifScalarConflict: (_|_){ // [eval] ifScalarConflict: conflicting values "soo" and 5 (mismatched types string and int): // ./in.cue:10:2 // ./in.cue:10:13 // ./in.cue:12:2 _#cond: (bool){ true } } ifScalarNested: (int){ 5 _#cond: (bool){ true } } } -- out/compile -- --- in.cue { ifScalar: { _#cond: true if 〈0;_#cond〉 { 5 } } ifScalarConflict: { _#cond: true if 〈0;_#cond〉 { 5 } "soo" } ifScalarNested: { _#cond: true if 〈0;_#cond〉 { { { 5 } } } } } cue-lang-cue-db9cc73/cue/token/000077500000000000000000000000001474664451600163745ustar00rootroot00000000000000cue-lang-cue-db9cc73/cue/token/position.go000066400000000000000000000344661474664451600206040ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package token import ( "cmp" "fmt" "sort" "sync" ) // ----------------------------------------------------------------------------- // Positions // Position describes an arbitrary source position // including the file, line, and column location. // A Position is valid if the line number is > 0. type Position struct { Filename string // filename, if any Offset int // offset, starting at 0 Line int // line number, starting at 1 Column int // column number, starting at 1 (byte count) // RelPos Pos // relative position information } // IsValid reports whether the position is valid. func (pos *Position) IsValid() bool { return pos.Line > 0 } // String returns a string in one of several forms: // // file:line:column valid position with file name // line:column valid position without file name // file invalid position with file name // - invalid position without file name func (pos Position) String() string { s := pos.Filename if pos.IsValid() { if s != "" { s += ":" } s += fmt.Sprintf("%d:%d", pos.Line, pos.Column) } if s == "" { s = "-" } return s } // Pos is a compact encoding of a source position within a file, as well as // relative positioning information. It can be converted into a Position for a // more convenient, but much larger, representation. type Pos struct { file *File offset int } // File returns the file that contains the position p or nil if there is no // such file (for instance for p == NoPos). func (p Pos) File() *File { if p.index() == 0 { return nil } return p.file } // TODO(mvdan): The methods below don't need to build an entire Position // just to access some of the information. This could matter particularly for // Compare, as it is called many times when sorting by position. func (p Pos) Line() int { if p.file == nil { return 0 } return p.Position().Line } func (p Pos) Column() int { if p.file == nil { return 0 } return p.Position().Column } func (p Pos) Filename() string { if p.file == nil { return "" } return p.Position().Filename } func (p Pos) Position() Position { if p.file == nil { return Position{} } return p.file.Position(p) } func (p Pos) String() string { return p.Position().String() } // Compare returns an integer comparing two positions. The result will be 0 if p == p2, // -1 if p < p2, and +1 if p > p2. Note that [NoPos] is always larger than any valid position. func (p Pos) Compare(p2 Pos) int { if p == p2 { return 0 } else if p == NoPos { return +1 } else if p2 == NoPos { return -1 } pos, pos2 := p.Position(), p2.Position() if c := cmp.Compare(pos.Filename, pos2.Filename); c != 0 { return c } // Note that CUE doesn't currently use any directives which alter // position information, like Go's //line, so comparing by offset is enough. return cmp.Compare(pos.Offset, pos2.Offset) } // NoPos is the zero value for [Pos]; there is no file and line information // associated with it, and [Pos.IsValid] is false. // // NoPos is always larger than any valid [Pos] value, as it tends to relate // to values produced from evaluating existing values with valid positions. // The corresponding [Position] value for NoPos is the zero value. var NoPos = Pos{} // RelPos indicates the relative position of token to the previous token. type RelPos int //go:generate go run golang.org/x/tools/cmd/stringer -type=RelPos -linecomment const ( // NoRelPos indicates no relative position is specified. NoRelPos RelPos = iota // invalid // Elided indicates that the token for which this position is defined is // not rendered at all. Elided // elided // NoSpace indicates there is no whitespace before this token. NoSpace // nospace // Blank means there is horizontal space before this token. Blank // blank // Newline means there is a single newline before this token. Newline // newline // NewSection means there are two or more newlines before this token. NewSection // section relMask = 0xf relShift = 4 ) func (p RelPos) Pos() Pos { return Pos{nil, int(p)} } // HasRelPos reports whether p has a relative position. func (p Pos) HasRelPos() bool { return p.offset&relMask != 0 } func (p Pos) Before(q Pos) bool { return p.file == q.file && p.Offset() < q.Offset() } // Offset reports the byte offset relative to the file. func (p Pos) Offset() int { return p.Position().Offset } // Add creates a new position relative to the p offset by n. func (p Pos) Add(n int) Pos { return Pos{p.file, p.offset + toPos(index(n))} } // IsValid reports whether the position is valid. func (p Pos) IsValid() bool { return p != NoPos } // IsNewline reports whether the relative information suggests this node should // be printed on a new line. func (p Pos) IsNewline() bool { return p.RelPos() >= Newline } func (p Pos) WithRel(rel RelPos) Pos { return Pos{p.file, p.offset&^relMask | int(rel)} } func (p Pos) RelPos() RelPos { return RelPos(p.offset & relMask) } func (p Pos) index() index { return index(p.offset) >> relShift } func toPos(x index) int { return (int(x) << relShift) } // ----------------------------------------------------------------------------- // File // index represents an offset into the file. // It's 1-based rather than zero-based so that // we can distinguish the zero Pos from a Pos that // just has a zero offset. type index int // A File has a name, size, and line offset table. type File struct { mutex sync.RWMutex name string // file name as provided to AddFile // base is deprecated and stored only so that [File.Base] // can continue to return the same value passed to [NewFile]. base index size index // file size as provided to AddFile // lines and infos are protected by set.mutex lines []index // lines contains the offset of the first character for each line (the first entry is always 0) infos []lineInfo } // NewFile returns a new file with the given OS file name. The size provides the // size of the whole file. // // The second argument is deprecated. It has no effect. func NewFile(filename string, deprecatedBase, size int) *File { if deprecatedBase < 0 { deprecatedBase = 1 } return &File{sync.RWMutex{}, filename, index(deprecatedBase), index(size), []index{0}, nil} } // Name returns the file name of file f as registered with AddFile. func (f *File) Name() string { return f.name } // Base returns the base offset of file f as passed to NewFile. // // Deprecated: this method just returns the (deprecated) second argument passed to NewFile. func (f *File) Base() int { return int(f.base) } // Size returns the size of file f as passed to NewFile. func (f *File) Size() int { return int(f.size) } // LineCount returns the number of lines in file f. func (f *File) LineCount() int { f.mutex.RLock() n := len(f.lines) f.mutex.RUnlock() return n } // AddLine adds the line offset for a new line. // The line offset must be larger than the offset for the previous line // and smaller than the file size; otherwise the line offset is ignored. func (f *File) AddLine(offset int) { x := index(offset) f.mutex.Lock() if i := len(f.lines); (i == 0 || f.lines[i-1] < x) && x < f.size { f.lines = append(f.lines, x) } f.mutex.Unlock() } // MergeLine merges a line with the following line. It is akin to replacing // the newline character at the end of the line with a space (to not change the // remaining offsets). To obtain the line number, consult e.g. Position.Line. // MergeLine will panic if given an invalid line number. func (f *File) MergeLine(line int) { if line <= 0 { panic("illegal line number (line numbering starts at 1)") } f.mutex.Lock() defer f.mutex.Unlock() if line >= len(f.lines) { panic("illegal line number") } // To merge the line numbered with the line numbered , // we need to remove the entry in lines corresponding to the line // numbered . The entry in lines corresponding to the line // numbered is located at index , since indices in lines // are 0-based and line numbers are 1-based. copy(f.lines[line:], f.lines[line+1:]) f.lines = f.lines[:len(f.lines)-1] } // Lines returns the effective line offset table of the form described by [File.SetLines]. // Callers must not mutate the result. func (f *File) Lines() []int { var lines []int f.mutex.Lock() // Unfortunate that we have to loop, but we use our own type. for _, line := range f.lines { lines = append(lines, int(line)) } f.mutex.Unlock() return lines } // SetLines sets the line offsets for a file and reports whether it succeeded. // The line offsets are the offsets of the first character of each line; // for instance for the content "ab\nc\n" the line offsets are {0, 3}. // An empty file has an empty line offset table. // Each line offset must be larger than the offset for the previous line // and smaller than the file size; otherwise SetLines fails and returns // false. // Callers must not mutate the provided slice after SetLines returns. func (f *File) SetLines(lines []int) bool { // verify validity of lines table size := f.size for i, offset := range lines { if i > 0 && offset <= lines[i-1] || size <= index(offset) { return false } } // set lines table f.mutex.Lock() f.lines = f.lines[:0] for _, l := range lines { f.lines = append(f.lines, index(l)) } f.mutex.Unlock() return true } // SetLinesForContent sets the line offsets for the given file content. // It ignores position-altering //line comments. func (f *File) SetLinesForContent(content []byte) { var lines []index line := index(0) for offset, b := range content { if line >= 0 { lines = append(lines, line) } line = -1 if b == '\n' { line = index(offset) + 1 } } // set lines table f.mutex.Lock() f.lines = lines f.mutex.Unlock() } // A lineInfo object describes alternative file and line number // information (such as provided via a //line comment in a .go // file) for a given file offset. type lineInfo struct { // fields are exported to make them accessible to gob Offset int Filename string Line int } // AddLineInfo adds alternative file and line number information for // a given file offset. The offset must be larger than the offset for // the previously added alternative line info and smaller than the // file size; otherwise the information is ignored. // // AddLineInfo is typically used to register alternative position // information for //line filename:line comments in source files. func (f *File) AddLineInfo(offset int, filename string, line int) { x := index(offset) f.mutex.Lock() if i := len(f.infos); i == 0 || index(f.infos[i-1].Offset) < x && x < f.size { f.infos = append(f.infos, lineInfo{offset, filename, line}) } f.mutex.Unlock() } // Pos returns the Pos value for the given file offset; // the offset must be <= f.Size(). // f.Pos(f.Offset(p)) == p. func (f *File) Pos(offset int, rel RelPos) Pos { if index(offset) > f.size { panic("illegal file offset") } return Pos{f, toPos(1+index(offset)) + int(rel)} } // Offset returns the offset for the given file position p; // p must be a valid Pos value in that file. // f.Offset(f.Pos(offset)) == offset. func (f *File) Offset(p Pos) int { x := p.index() if x < 1 || x > 1+index(f.size) { panic("illegal Pos value") } return int(x - 1) } // Line returns the line number for the given file position p; // p must be a Pos value in that file or NoPos. func (f *File) Line(p Pos) int { return f.Position(p).Line } func searchLineInfos(a []lineInfo, x int) int { return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1 } // unpack returns the filename and line and column number for a file offset. // If adjusted is set, unpack will return the filename and line information // possibly adjusted by //line comments; otherwise those comments are ignored. func (f *File) unpack(offset index, adjusted bool) (filename string, line, column int) { filename = f.name if i := searchInts(f.lines, offset); i >= 0 { line, column = int(i+1), int(offset-f.lines[i]+1) } if adjusted && len(f.infos) > 0 { // almost no files have extra line infos if i := searchLineInfos(f.infos, int(offset)); i >= 0 { alt := &f.infos[i] filename = alt.Filename if i := searchInts(f.lines, index(alt.Offset)); i >= 0 { line += alt.Line - i - 1 } } } return } func (f *File) position(p Pos, adjusted bool) (pos Position) { offset := p.index() - 1 pos.Offset = int(offset) pos.Filename, pos.Line, pos.Column = f.unpack(offset, adjusted) return } // PositionFor returns the Position value for the given file position p. // If adjusted is set, the position may be adjusted by position-altering // //line comments; otherwise those comments are ignored. // p must be a Pos value in f or NoPos. func (f *File) PositionFor(p Pos, adjusted bool) (pos Position) { x := p.index() if p != NoPos { if x < 1 || x > 1+f.size { panic("illegal Pos value") } pos = f.position(p, adjusted) } return } // Position returns the Position value for the given file position p. // Calling f.Position(p) is equivalent to calling f.PositionFor(p, true). func (f *File) Position(p Pos) (pos Position) { return f.PositionFor(p, true) } // ----------------------------------------------------------------------------- // Helper functions func searchInts(a []index, x index) int { // This function body is a manually inlined version of: // // return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1 // // With better compiler optimizations, this may not be needed in the // future, but at the moment this change improves the go/printer // benchmark performance by ~30%. This has a direct impact on the // speed of gofmt and thus seems worthwhile (2011-04-29). // TODO(gri): Remove this when compilers have caught up. i, j := 0, len(a) for i < j { h := i + (j-i)/2 // avoid overflow when computing h // i ≤ h < j if a[h] <= x { i = h + 1 } else { j = h } } return i - 1 } cue-lang-cue-db9cc73/cue/token/position_test.go000066400000000000000000000156631474664451600216410ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package token import ( "fmt" "slices" "testing" ) func checkPos(t *testing.T, msg string, got, want Position) { if got.Filename != want.Filename { t.Errorf("%s: got filename = %q; want %q", msg, got.Filename, want.Filename) } if got.Offset != want.Offset { t.Errorf("%s: got offset = %d; want %d", msg, got.Offset, want.Offset) } if got.Line != want.Line { t.Errorf("%s: got line = %d; want %d", msg, got.Line, want.Line) } if got.Column != want.Column { t.Errorf("%s: got column = %d; want %d", msg, got.Column, want.Column) } } func TestNoPos(t *testing.T) { if NoPos.IsValid() { t.Errorf("NoPos should not be valid") } checkPos(t, "nil NoPos", NoPos.Position(), Position{}) } var tests = []struct { filename string source []byte // may be nil size int lines []int }{ {"a", []byte{}, 0, []int{}}, {"b", []byte("01234"), 5, []int{0}}, {"c", []byte("\n\n\n\n\n\n\n\n\n"), 9, []int{0, 1, 2, 3, 4, 5, 6, 7, 8}}, {"d", nil, 100, []int{0, 5, 10, 20, 30, 70, 71, 72, 80, 85, 90, 99}}, {"e", nil, 777, []int{0, 80, 100, 120, 130, 180, 267, 455, 500, 567, 620}}, {"f", []byte("package p\n\nimport \"fmt\""), 23, []int{0, 10, 11}}, {"g", []byte("package p\n\nimport \"fmt\"\n"), 24, []int{0, 10, 11}}, {"h", []byte("package p\n\nimport \"fmt\"\n "), 25, []int{0, 10, 11, 24}}, } func linecol(lines []int, offs int) (int, int) { prevLineOffs := 0 for line, lineOffs := range lines { if offs < lineOffs { return line, offs - prevLineOffs + 1 } prevLineOffs = lineOffs } return len(lines), offs - prevLineOffs + 1 } func verifyPositions(t *testing.T, f *File, lines []int) { if got := f.Lines(); !slices.Equal(got, lines) { t.Fatalf("File.Lines got %v instead of %v", got, lines) } for offs := 0; offs < f.Size(); offs++ { p := f.Pos(offs, 0) offs2 := f.Offset(p) if offs2 != offs { t.Errorf("%s, Offset: got offset %d; want %d", f.Name(), offs2, offs) } line, col := linecol(lines, offs) msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p.offset) checkPos(t, msg, f.Pos(offs, 0).Position(), Position{f.Name(), offs, line, col}) checkPos(t, msg, p.Position(), Position{f.Name(), offs, line, col}) } } func makeTestSource(size int, lines []int) []byte { src := make([]byte, size) for _, offs := range lines { if offs > 0 { src[offs-1] = '\n' } } return src } func TestPositions(t *testing.T) { const delta = 7 // a non-zero base offset increment for _, test := range tests { // verify consistency of test case if test.source != nil && len(test.source) != test.size { t.Errorf("%s: inconsistent test case: got file size %d; want %d", test.filename, len(test.source), test.size) } // add file and verify name and size f := NewFile(test.filename, 1+delta, test.size) if f.Name() != test.filename { t.Errorf("got filename %q; want %q", f.Name(), test.filename) } if f.Size() != test.size { t.Errorf("%s: got file size %d; want %d", f.Name(), f.Size(), test.size) } if f.Pos(0, 0).file != f { t.Errorf("%s: f.Pos(0, 0) was not found in f", f.Name()) } // add lines individually and verify all positions for i, offset := range test.lines { f.AddLine(offset) if f.LineCount() != i+1 { t.Errorf("%s, AddLine: got line count %d; want %d", f.Name(), f.LineCount(), i+1) } // adding the same offset again should be ignored f.AddLine(offset) if f.LineCount() != i+1 { t.Errorf("%s, AddLine: got unchanged line count %d; want %d", f.Name(), f.LineCount(), i+1) } verifyPositions(t, f, test.lines[0:i+1]) } // add lines with SetLines and verify all positions if ok := f.SetLines(test.lines); !ok { t.Errorf("%s: SetLines failed", f.Name()) } if f.LineCount() != len(test.lines) { t.Errorf("%s, SetLines: got line count %d; want %d", f.Name(), f.LineCount(), len(test.lines)) } verifyPositions(t, f, test.lines) // add lines with SetLinesForContent and verify all positions src := test.source if src == nil { // no test source available - create one from scratch src = makeTestSource(test.size, test.lines) } f.SetLinesForContent(src) if f.LineCount() != len(test.lines) { t.Errorf("%s, SetLinesForContent: got line count %d; want %d", f.Name(), f.LineCount(), len(test.lines)) } verifyPositions(t, f, test.lines) } } func TestLineInfo(t *testing.T) { f := NewFile("foo", 1, 500) lines := []int{0, 42, 77, 100, 210, 220, 277, 300, 333, 401} // add lines individually and provide alternative line information for _, offs := range lines { f.AddLine(offs) f.AddLineInfo(offs, "bar", 42) } // verify positions for all offsets for offs := 0; offs <= f.Size(); offs++ { p := f.Pos(offs, 0) _, col := linecol(lines, offs) msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p.offset) checkPos(t, msg, f.Position(f.Pos(offs, 0)), Position{"bar", offs, 42, col}) checkPos(t, msg, p.Position(), Position{"bar", offs, 42, col}) } } func TestPositionFor(t *testing.T) { src := []byte(` foo b ar //line :100 foobar //line bar:3 done `) const filename = "foo" f := NewFile(filename, 1, len(src)) f.SetLinesForContent(src) // verify position info for i, offs := range f.lines { got1 := f.PositionFor(f.Pos(int(offs), 0), false) got2 := f.PositionFor(f.Pos(int(offs), 0), true) got3 := f.Position(f.Pos(int(offs), 0)) want := Position{filename, int(offs), i + 1, 1} checkPos(t, "1. PositionFor unadjusted", got1, want) checkPos(t, "1. PositionFor adjusted", got2, want) checkPos(t, "1. Position", got3, want) } // manually add //line info on lines l1, l2 const l1, l2 = 5, 7 f.AddLineInfo(int(f.lines[l1-1]), "", 100) f.AddLineInfo(int(f.lines[l2-1]), "bar", 3) // unadjusted position info must remain unchanged for i, offs := range f.lines { got1 := f.PositionFor(f.Pos(int(offs), 0), false) want := Position{filename, int(offs), i + 1, 1} checkPos(t, "2. PositionFor unadjusted", got1, want) } // adjusted position info should have changed for i, offs := range f.lines { got2 := f.PositionFor(f.Pos(int(offs), 0), true) got3 := f.Position(f.Pos(int(offs), 0)) want := Position{filename, int(offs), i + 1, 1} // manually compute wanted filename and line line := want.Line if i+1 >= l1 { want.Filename = "" want.Line = line - l1 + 100 } if i+1 >= l2 { want.Filename = "bar" want.Line = line - l2 + 3 } checkPos(t, "3. PositionFor adjusted", got2, want) checkPos(t, "3. Position", got3, want) } } cue-lang-cue-db9cc73/cue/token/relpos_string.go000066400000000000000000000013241474664451600216150ustar00rootroot00000000000000// Code generated by "stringer -type=RelPos -linecomment"; DO NOT EDIT. package token import "strconv" func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[NoRelPos-0] _ = x[Elided-1] _ = x[NoSpace-2] _ = x[Blank-3] _ = x[Newline-4] _ = x[NewSection-5] } const _RelPos_name = "invalidelidednospaceblanknewlinesection" var _RelPos_index = [...]uint8{0, 7, 13, 20, 25, 32, 39} func (i RelPos) String() string { if i < 0 || i >= RelPos(len(_RelPos_index)-1) { return "RelPos(" + strconv.FormatInt(int64(i), 10) + ")" } return _RelPos_name[_RelPos_index[i]:_RelPos_index[i+1]] } cue-lang-cue-db9cc73/cue/token/token.go000066400000000000000000000075731474664451600200570ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package token defines constants representing the lexical tokens of the Go // programming language and basic operations on tokens (printing, predicates). package token // Token is the set of lexical tokens of the CUE configuration language. type Token int //go:generate go run golang.org/x/tools/cmd/stringer -type=Token -linecomment // The list of tokens. const ( // Special tokens ILLEGAL Token = iota EOF COMMENT // e.g. @foo(bar,baz=4) ATTRIBUTE // Identifiers and basic type literals // (these tokens stand for classes of literals) literalBeg // e.g. main, _tmp IDENT // e.g. 12_345Mi, 0700, 0xdeadbeef, 1.2M INT // e.g. 123.45 FLOAT // e.g. 3m4s; TODO // DURATION // e.g. "abc" STRING // a part of a template string, e.g. `"age: \(` INTERPOLATION BOTTOM // _|_ literalEnd // Operators and delimiters operatorBeg ADD // + SUB // - MUL // * POW // ^ QUO // / IQUO // quo IREM // rem IDIV // div IMOD // mod AND // & OR // | LAND // && LOR // || BIND // = EQL // == LSS // < GTR // > NOT // ! ARROW // <- NEQ // != LEQ // <= GEQ // >= MAT // =~ NMAT // !~ LPAREN // ( LBRACK // [ LBRACE // { COMMA // , PERIOD // . ELLIPSIS // ... RPAREN // ) RBRACK // ] RBRACE // } SEMICOLON // ; COLON // : OPTION // ? operatorEnd keywordBeg IF // if FOR // for IN // in LET // let // experimental FUNC // func TRUE // true FALSE // false NULL // null keywordEnd ) // A set of constants for precedence-based expression parsing. // Non-operators have lowest precedence, followed by operators // starting with precedence 1 up to unary operators. The highest // precedence serves as "catch-all" precedence for selector, // indexing, and other operator and delimiter tokens. const ( LowestPrec = lowestPrec UnaryPrec = unaryPrec HighestPrec = highestPrec ) const ( lowestPrec = 0 // non-operators unaryPrec = 8 highestPrec = 9 ) // Precedence returns the operator precedence of the binary // operator op. If op is not a binary operator, the result // is LowestPrecedence. func (tok Token) Precedence() int { switch tok { case OR: return 1 case AND: return 2 case LOR: return 3 case LAND: return 4 case EQL, NEQ, LSS, LEQ, GTR, GEQ, MAT, NMAT: return 5 case ADD, SUB: return 6 case MUL, QUO, IDIV, IMOD, IQUO, IREM: return 7 } return lowestPrec } var keywords map[string]Token func init() { keywords = make(map[string]Token) for tok := keywordBeg + 1; tok < keywordEnd; tok++ { keywords[tok.String()] = tok } } // Lookup maps an identifier to its keyword token or IDENT (if not a keyword). func Lookup(ident string) Token { if tok, isKeyword := keywords[ident]; isKeyword { return tok } return IDENT } // Predicates // IsLiteral returns true for tokens corresponding to identifiers // and basic type literals; it returns false otherwise. func (tok Token) IsLiteral() bool { return literalBeg < tok && tok < literalEnd } // IsOperator returns true for tokens corresponding to operators and // delimiters; it returns false otherwise. func (tok Token) IsOperator() bool { return operatorBeg < tok && tok < operatorEnd } // IsKeyword returns true for tokens corresponding to keywords; // it returns false otherwise. func (tok Token) IsKeyword() bool { return keywordBeg < tok && tok < keywordEnd } cue-lang-cue-db9cc73/cue/token/token_string.go000066400000000000000000000037771474664451600214470ustar00rootroot00000000000000// Code generated by "stringer -type=Token -linecomment"; DO NOT EDIT. package token import "strconv" func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[ILLEGAL-0] _ = x[EOF-1] _ = x[COMMENT-2] _ = x[ATTRIBUTE-3] _ = x[literalBeg-4] _ = x[IDENT-5] _ = x[INT-6] _ = x[FLOAT-7] _ = x[STRING-8] _ = x[INTERPOLATION-9] _ = x[BOTTOM-10] _ = x[literalEnd-11] _ = x[operatorBeg-12] _ = x[ADD-13] _ = x[SUB-14] _ = x[MUL-15] _ = x[POW-16] _ = x[QUO-17] _ = x[IQUO-18] _ = x[IREM-19] _ = x[IDIV-20] _ = x[IMOD-21] _ = x[AND-22] _ = x[OR-23] _ = x[LAND-24] _ = x[LOR-25] _ = x[BIND-26] _ = x[EQL-27] _ = x[LSS-28] _ = x[GTR-29] _ = x[NOT-30] _ = x[ARROW-31] _ = x[NEQ-32] _ = x[LEQ-33] _ = x[GEQ-34] _ = x[MAT-35] _ = x[NMAT-36] _ = x[LPAREN-37] _ = x[LBRACK-38] _ = x[LBRACE-39] _ = x[COMMA-40] _ = x[PERIOD-41] _ = x[ELLIPSIS-42] _ = x[RPAREN-43] _ = x[RBRACK-44] _ = x[RBRACE-45] _ = x[SEMICOLON-46] _ = x[COLON-47] _ = x[OPTION-48] _ = x[operatorEnd-49] _ = x[keywordBeg-50] _ = x[IF-51] _ = x[FOR-52] _ = x[IN-53] _ = x[LET-54] _ = x[FUNC-55] _ = x[TRUE-56] _ = x[FALSE-57] _ = x[NULL-58] _ = x[keywordEnd-59] } const _Token_name = "ILLEGALEOFCOMMENTATTRIBUTEliteralBegIDENTINTFLOATSTRINGINTERPOLATION_|_literalEndoperatorBeg+-*^/quoremdivmod&|&&||===<>!<-!=<=>==~!~([{,....)]};:?operatorEndkeywordBegifforinletfunctruefalsenullkeywordEnd" var _Token_index = [...]uint8{0, 7, 10, 17, 26, 36, 41, 44, 49, 55, 68, 71, 81, 92, 93, 94, 95, 96, 97, 100, 103, 106, 109, 110, 111, 113, 115, 116, 118, 119, 120, 121, 123, 125, 127, 129, 131, 133, 134, 135, 136, 137, 138, 141, 142, 143, 144, 145, 146, 147, 158, 168, 170, 173, 175, 178, 182, 186, 191, 195, 205} func (i Token) String() string { if i < 0 || i >= Token(len(_Token_index)-1) { return "Token(" + strconv.FormatInt(int64(i), 10) + ")" } return _Token_name[_Token_index[i]:_Token_index[i+1]] } cue-lang-cue-db9cc73/cue/types.go000066400000000000000000002004371474664451600167550ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import ( "bytes" "encoding/json" "fmt" "io" "math" "math/big" "strings" "github.com/cockroachdb/apd/v3" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/compile" "cuelang.org/go/internal/core/convert" "cuelang.org/go/internal/core/export" "cuelang.org/go/internal/core/runtime" "cuelang.org/go/internal/core/subsume" "cuelang.org/go/internal/core/validate" internaljson "cuelang.org/go/internal/encoding/json" "cuelang.org/go/internal/types" ) // Kind determines the underlying type of a Value. type Kind = adt.Kind const ( // BottomKind represents the bottom value. BottomKind Kind = adt.BottomKind // NullKind indicates a null value. NullKind Kind = adt.NullKind // BoolKind indicates a boolean value. BoolKind Kind = adt.BoolKind // IntKind represents an integral number. IntKind Kind = adt.IntKind // FloatKind represents a decimal float point number that cannot be // converted to an integer. The underlying number may still be integral, // but resulting from an operation that enforces the float type. FloatKind Kind = adt.FloatKind // StringKind indicates any kind of string. StringKind Kind = adt.StringKind // BytesKind is a blob of data. BytesKind Kind = adt.BytesKind // StructKind is a kev-value map. StructKind Kind = adt.StructKind // ListKind indicates a list of values. ListKind Kind = adt.ListKind // _numberKind is used as a implementation detail inside // Kind.String to indicate NumberKind. // NumberKind represents any kind of number. NumberKind Kind = adt.NumberKind // TopKind represents the top value. TopKind Kind = adt.TopKind ) // An structValue represents a JSON object. // // TODO: remove type structValue struct { ctx *adt.OpContext v Value obj *adt.Vertex arcs []*adt.Vertex } type hiddenStructValue = structValue // Len reports the number of fields in this struct. func (o *hiddenStructValue) Len() int { if o.obj == nil { return 0 } return len(o.arcs) } // At reports the key and value of the ith field, i < o.Len(). func (o *hiddenStructValue) At(i int) (key string, v Value) { arc := o.arcs[i] return o.v.idx.LabelStr(arc.Label), newChildValue(o, i) } func (o *hiddenStructValue) at(i int) *adt.Vertex { return o.arcs[i] } // Lookup reports the field for the given key. The returned [Value] is invalid // if it does not exist. func (o *hiddenStructValue) Lookup(key string) Value { f := o.v.idx.StrLabel(key) i := 0 len := o.Len() for ; i < len; i++ { if o.arcs[i].Label == f { break } } if i == len { x := mkErr(o.obj, 0, "field not found: %v", key) x.NotExists = true // TODO: more specifically we should test whether the values that // are addressable from the root of the configuration can support the // looked up value. This will avoid false positives such as when // an open literal struct is passed to a builtin. if o.obj.Accept(o.ctx, f) { x.Code = adt.IncompleteError } return newErrValue(o.v, x) } return newChildValue(o, i) } // MarshalJSON returns a valid JSON encoding or reports an error if any of the // fields is invalid. func (o *structValue) appendJSON(b []byte) ([]byte, error) { b = append(b, '{') n := o.Len() for i := range n { k, v := o.At(i) // Do not use json.Marshal as it escapes HTML. s, err := internaljson.Marshal(k) if err != nil { return nil, err } b = append(b, s...) b = append(b, ':') b, err = v.appendJSON(o.ctx, b) if err != nil { return nil, err } if i < n-1 { b = append(b, ',') } } b = append(b, '}') return b, nil } var _ errors.Error = &marshalError{} type marshalError struct { err errors.Error b *adt.Bottom } func toMarshalErr(v Value, b *adt.Bottom) error { return &marshalError{v.toErr(b), b} } func marshalErrf(v Value, src adt.Node, code adt.ErrorCode, msg string, args ...interface{}) error { arguments := append([]interface{}{code, msg}, args...) b := mkErr(src, arguments...) return toMarshalErr(v, b) } func (e *marshalError) Error() string { return fmt.Sprintf("cue: marshal error: %v", e.err) } func (e *marshalError) Bottom() *adt.Bottom { return e.b } func (e *marshalError) Path() []string { return e.err.Path() } func (e *marshalError) Msg() (string, []interface{}) { return e.err.Msg() } func (e *marshalError) Position() token.Pos { return e.err.Position() } func (e *marshalError) InputPositions() []token.Pos { return e.err.InputPositions() } func unwrapJSONError(err error) errors.Error { switch x := err.(type) { case *json.MarshalerError: return unwrapJSONError(x.Err) case *marshalError: return x case errors.Error: return &marshalError{x, nil} default: return &marshalError{errors.Wrapf(err, token.NoPos, "json error"), nil} } } // An Iterator iterates over values. type Iterator struct { val Value idx *runtime.Runtime ctx *adt.OpContext arcs []*adt.Vertex p int cur Value f adt.Feature arcType adt.ArcType } type hiddenIterator = Iterator // Next advances the iterator to the next value and reports whether there was any. // It must be called before the first call to [Iterator.Value] or [Iterator.Selector]. func (i *Iterator) Next() bool { if i.p >= len(i.arcs) { i.cur = Value{} return false } arc := i.arcs[i.p] arc.Finalize(i.ctx) p := linkParent(i.val.parent_, i.val.v, arc) i.f = arc.Label i.arcType = arc.ArcType i.cur = makeValue(i.val.idx, arc, p) i.p++ return true } // Value returns the current value in the list. // It will panic if [Iterator.Next] advanced past the last entry. func (i *Iterator) Value() Value { return i.cur } // Selector reports the field label of this iteration. func (i *Iterator) Selector() Selector { sel := featureToSel(i.f, i.idx) // Only call wrapConstraint if there is any constraint type to wrap with. if ctype := fromArcType(i.arcType); ctype != 0 { sel = wrapConstraint(sel, ctype) } return sel } // Label reports the label of the value if i iterates over struct fields and "" // otherwise. // // Deprecated: use [Iterator.Selector] with methods like // [Selector.Unquoted] or [Selector.String] depending on whether or not // you are only dealing with regular fields, whose labels are always [StringLabel]. // Note that this will give more accurate string representations. func (i *hiddenIterator) Label() string { if i.f == 0 { return "" } return i.idx.LabelStr(i.f) } // IsOptional reports if a field is optional. func (i *Iterator) IsOptional() bool { return i.arcType == adt.ArcOptional } // FieldType reports the type of the field. func (i *Iterator) FieldType() SelectorType { return featureToSelType(i.f, i.arcType) } // marshalJSON iterates over the list and generates JSON output. HasNext // will return false after this operation. func listAppendJSON(b []byte, l *Iterator) ([]byte, error) { b = append(b, '[') if l.Next() { for i := 0; ; i++ { var err error b, err = l.Value().appendJSON(l.ctx, b) if err != nil { return nil, err } if !l.Next() { break } b = append(b, ',') } } b = append(b, ']') return b, nil } func (v Value) getNum(k adt.Kind) (*adt.Num, errors.Error) { v, _ = v.Default() ctx := v.ctx() if err := v.checkKind(ctx, k); err != nil { return nil, v.toErr(err) } n, _ := v.eval(ctx).(*adt.Num) return n, nil } // MantExp breaks x into its mantissa and exponent components and returns the // exponent. If a non-nil mant argument is provided its value is set to the // mantissa of x. The components satisfy x == mant × 10**exp. It returns an // error if v is not a number. // // The components are not normalized. For instance, 2.00 is represented mant == // 200 and exp == -2. Calling MantExp with a nil argument is an efficient way to // get the exponent of the receiver. func (v Value) MantExp(mant *big.Int) (exp int, err error) { n, err := v.getNum(adt.NumberKind) if err != nil { return 0, err } if n.X.Form != 0 { return 0, ErrInfinite } if mant != nil { mant.Set(n.X.Coeff.MathBigInt()) if n.X.Negative { mant.Neg(mant) } } return int(n.X.Exponent), nil } // Decimal is for internal use only. The Decimal type that is returned is // subject to change. func (v hiddenValue) Decimal() (d *internal.Decimal, err error) { n, err := v.getNum(adt.NumberKind) if err != nil { return nil, err } return &n.X, nil } // AppendInt appends the string representation of x in the given base to buf and // returns the extended buffer, or an error if the underlying number was not // an integer. func (v Value) AppendInt(buf []byte, base int) ([]byte, error) { i, err := v.Int(nil) if err != nil { return nil, err } return i.Append(buf, base), nil } // AppendFloat appends to buf the string form of the floating-point number x. // It returns an error if v is not a number. func (v Value) AppendFloat(buf []byte, fmt byte, prec int) ([]byte, error) { n, err := v.getNum(adt.NumberKind) if err != nil { return nil, err } ctx := internal.BaseContext nd := int(apd.NumDigits(&n.X.Coeff)) + int(n.X.Exponent) if n.X.Form == apd.Infinite { if n.X.Negative { buf = append(buf, '-') } return append(buf, string('∞')...), nil } if fmt == 'f' && nd > 0 { ctx = ctx.WithPrecision(uint32(nd + prec)) } else { ctx = ctx.WithPrecision(uint32(prec)) } var d apd.Decimal ctx.Round(&d, &n.X) return d.Append(buf, fmt), nil } var ( // ErrBelow indicates that a value was rounded down in a conversion. ErrBelow = errors.New("value was rounded down") // ErrAbove indicates that a value was rounded up in a conversion. ErrAbove = errors.New("value was rounded up") // ErrInfinite indicates that a value is infinite. ErrInfinite = errors.New("infinite") ) // Int converts the underlying integral number to an big.Int. It reports an // error if the underlying value is not an integer type. If a non-nil *Int // argument z is provided, Int stores the result in z instead of allocating a // new Int. func (v Value) Int(z *big.Int) (*big.Int, error) { n, err := v.getNum(adt.IntKind) if err != nil { return nil, err } if z == nil { z = &big.Int{} } if n.X.Exponent != 0 { panic("cue: exponent should always be nil for integer types") } z.Set(n.X.Coeff.MathBigInt()) if n.X.Negative { z.Neg(z) } return z, nil } // Int64 converts the underlying integral number to int64. It reports an // error if the underlying value is not an integer type or cannot be represented // as an int64. The result is (math.MinInt64, ErrAbove) for x < math.MinInt64, // and (math.MaxInt64, ErrBelow) for x > math.MaxInt64. func (v Value) Int64() (int64, error) { n, err := v.getNum(adt.IntKind) if err != nil { return 0, err } if !n.X.Coeff.IsInt64() { if n.X.Negative { return math.MinInt64, ErrAbove } return math.MaxInt64, ErrBelow } i := n.X.Coeff.Int64() if n.X.Negative { i = -i } return i, nil } // Uint64 converts the underlying integral number to uint64. It reports an // error if the underlying value is not an integer type or cannot be represented // as a uint64. The result is (0, ErrAbove) for x < 0, and // (math.MaxUint64, ErrBelow) for x > math.MaxUint64. func (v Value) Uint64() (uint64, error) { n, err := v.getNum(adt.IntKind) if err != nil { return 0, err } if n.X.Negative { return 0, ErrAbove } if !n.X.Coeff.IsUint64() { return math.MaxUint64, ErrBelow } i := n.X.Coeff.Uint64() return i, nil } var ( smallestPosFloat64 *apd.Decimal smallestNegFloat64 *apd.Decimal maxPosFloat64 *apd.Decimal maxNegFloat64 *apd.Decimal ) func init() { const ( // math.SmallestNonzeroFloat64: 1 / 2**(1023 - 1 + 52) smallest = "4.940656458412465441765687928682213723651e-324" // math.MaxFloat64: 2**1023 * (2**53 - 1) / 2**52 max = "1.797693134862315708145274237317043567981e+308" ) ctx := internal.BaseContext.WithPrecision(40) var err error smallestPosFloat64, _, err = ctx.NewFromString(smallest) if err != nil { panic(err) } smallestNegFloat64, _, err = ctx.NewFromString("-" + smallest) if err != nil { panic(err) } maxPosFloat64, _, err = ctx.NewFromString(max) if err != nil { panic(err) } maxNegFloat64, _, err = ctx.NewFromString("-" + max) if err != nil { panic(err) } } // Float64 returns the float64 value nearest to x. It reports an error if v is // not a number. If x is too small to be represented by a float64 (|x| < // math.SmallestNonzeroFloat64), the result is (0, ErrBelow) or (-0, ErrAbove), // respectively, depending on the sign of x. If x is too large to be represented // by a float64 (|x| > math.MaxFloat64), the result is (+Inf, ErrAbove) or // (-Inf, ErrBelow), depending on the sign of x. func (v Value) Float64() (float64, error) { n, err := v.getNum(adt.NumberKind) if err != nil { return 0, err } if n.X.IsZero() { return 0.0, nil } if n.X.Negative { if n.X.Cmp(smallestNegFloat64) == 1 { return -0, ErrAbove } if n.X.Cmp(maxNegFloat64) == -1 { return math.Inf(-1), ErrBelow } } else { if n.X.Cmp(smallestPosFloat64) == -1 { return 0, ErrBelow } if n.X.Cmp(maxPosFloat64) == 1 { return math.Inf(1), ErrAbove } } f, _ := n.X.Float64() return f, nil } // Value holds any value, which may be a Boolean, Error, List, Null, Number, // Struct, or String. type Value struct { idx *runtime.Runtime v *adt.Vertex // Parent keeps track of the parent if the value corresponding to v.Parent // differs, recursively. parent_ *parent } // parent is a distinct type from Value to ensure more type safety: Value // is typically used by value, so taking a pointer to it has a high risk // or globbering the contents. type parent struct { v *adt.Vertex p *parent } func (v Value) parent() Value { switch { case v.v == nil: return Value{} case v.parent_ != nil: return Value{v.idx, v.parent_.v, v.parent_.p} default: return Value{v.idx, v.v.Parent, nil} } } type valueScope Value func (v valueScope) Vertex() *adt.Vertex { return v.v } func (v valueScope) Parent() compile.Scope { p := Value(v).parent() if p.v == nil { return nil } return valueScope(p) } type hiddenValue = Value // Core is for internal use only. func (v hiddenValue) Core(x *types.Value) { x.V = v.v x.R = v.idx } func newErrValue(v Value, b *adt.Bottom) Value { node := &adt.Vertex{BaseValue: b} if v.v != nil { node.Label = v.v.Label node.Parent = v.v.Parent } node.ForceDone() node.AddConjunct(adt.MakeRootConjunct(nil, b)) return makeChildValue(v.parent(), node) } func newVertexRoot(idx *runtime.Runtime, ctx *adt.OpContext, x *adt.Vertex) Value { if ctx != nil { // This is indicative of an zero Value. In some cases this is called // with an error value. x.Finalize(ctx) } else { x.ForceDone() } return makeValue(idx, x, nil) } func newValueRoot(idx *runtime.Runtime, ctx *adt.OpContext, x adt.Expr) Value { if n, ok := x.(*adt.Vertex); ok { return newVertexRoot(idx, ctx, n) } node := &adt.Vertex{} node.AddConjunct(adt.MakeRootConjunct(nil, x)) return newVertexRoot(idx, ctx, node) } func newChildValue(o *structValue, i int) Value { arc := o.at(i) // TODO: fix linkage to parent. return makeValue(o.v.idx, arc, linkParent(o.v.parent_, o.v.v, arc)) } // Dereference reports the value v refers to if v is a reference or v itself // otherwise. func Dereference(v Value) Value { n := v.v if n == nil { return v } c, count := n.SingleConjunct() if count != 1 { return v } env, expr := c.EnvExpr() // TODO: consider supporting unwrapping of structs or comprehensions around // a single embedded reference. r, _ := expr.(adt.Resolver) if r == nil { return v } c = adt.MakeRootConjunct(env, expr) ctx := v.ctx() n, b := ctx.Resolve(c, r) if b != nil { return newErrValue(v, b) } n.Finalize(ctx) // NOTE: due to structure sharing, the path of the referred node may end // up different from the one explicitly pointed to. The value will be the // same, but the scope may differ. // TODO(structureshare): see if we can construct the original path. This // only has to be done if structures are being shared. return makeValue(v.idx, n, nil) } func makeValue(idx *runtime.Runtime, v *adt.Vertex, p *parent) Value { if v.Status() == 0 || v.BaseValue == nil { panic(fmt.Sprintf("not properly initialized (state: %v, value: %T)", v.Status(), v.BaseValue)) } return Value{idx, v, p} } // makeChildValue makes a new value, of which p is the parent, and links the // parent pointer to p if necessary. func makeChildValue(p Value, arc *adt.Vertex) Value { return makeValue(p.idx, arc, linkParent(p.parent_, p.v, arc)) } // linkParent creates the parent struct for an arc, if necessary. // // The parent struct is necessary if the parent struct also has a parent struct, // or if arc is (structurally) shared and does not have node as a parent. func linkParent(p *parent, node, arc *adt.Vertex) *parent { if p == nil && node == arc.Parent { return nil } return &parent{node, p} } func remakeValue(base Value, env *adt.Environment, v adt.Expr) Value { // TODO: right now this is necessary because disjunctions do not have // populated conjuncts. if v, ok := v.(*adt.Vertex); ok && !v.IsUnprocessed() { return Value{base.idx, v, nil} } n := &adt.Vertex{Label: base.v.Label} n.AddConjunct(adt.MakeRootConjunct(env, v)) n = manifest(base.ctx(), n) n.Parent = base.v.Parent return makeChildValue(base.parent(), n) } func remakeFinal(base Value, v adt.Value) Value { n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label, BaseValue: v} n.ForceDone() return makeChildValue(base.parent(), n) } func (v Value) ctx() *adt.OpContext { return newContext(v.idx) } // Eval resolves the references of a value and returns the result. // This method is not necessary to obtain concrete values. func (v Value) Eval() Value { if v.v == nil { return v } x := v.v // x = eval.FinalizeValue(v.idx.Runtime, v.v) // x.Finalize(v.ctx()) x = x.ToDataSingle() return makeValue(v.idx, x, v.parent_) // return remakeValue(v, nil, ctx.value(x)) } // Default reports the default value and whether it existed. It returns the // normal value if there is no default. func (v Value) Default() (Value, bool) { if v.v == nil { return v, false } d := v.v.Default() if d == v.v { return v, false } return makeValue(v.idx, d, v.parent_), true } // Label reports he label used to obtain this value from the enclosing struct. // // TODO: get rid of this somehow. Probably by including a FieldInfo struct // or the like. func (v hiddenValue) Label() (string, bool) { if v.v == nil || v.v.Label == 0 { return "", false } return v.idx.LabelStr(v.v.Label), true } // Kind returns the kind of value. It returns BottomKind for atomic values that // are not concrete. For instance, it will return BottomKind for the bounds // >=0. func (v Value) Kind() Kind { if v.v == nil { return BottomKind } w := v.v.DerefValue() c := w.BaseValue if !w.IsConcrete() { return BottomKind } return c.Kind() } // IncompleteKind returns a mask of all kinds that this value may be. func (v Value) IncompleteKind() Kind { if v.v == nil { return BottomKind } return v.v.Kind() } // MarshalJSON marshalls this value into valid JSON. func (v Value) MarshalJSON() (b []byte, err error) { b, err = v.appendJSON(v.ctx(), nil) if err != nil { return nil, unwrapJSONError(err) } return b, nil } func (v Value) appendJSON(ctx *adt.OpContext, b []byte) ([]byte, error) { v, _ = v.Default() if v.v == nil { return append(b, "null"...), nil } x := v.eval(ctx) if _, ok := x.(adt.Resolver); ok { return nil, marshalErrf(v, x, adt.IncompleteError, "value %q contains unresolved references", str(ctx, x)) } if !adt.IsConcrete(x) { return nil, marshalErrf(v, x, adt.IncompleteError, "cannot convert incomplete value %q to JSON", str(ctx, x)) } // TODO: implement marshalles in value. switch k := x.Kind(); k { case adt.NullKind: return append(b, "null"...), nil case adt.BoolKind: b2, err := json.Marshal(x.(*adt.Bool).B) return append(b, b2...), err case adt.IntKind, adt.FloatKind, adt.NumberKind: // [apd.Decimal] offers no [json.Marshaler] method, // however the "G" formatting appears to result in valid JSON // for any valid CUE number that we've come across so far. // Upstream also rejected adding JSON methods in favor of [encoding.TextMarshaler]. // // As an optimization, use the append-like API directly which is equivalent to // [apd.Decimal.MarshalText], allowing us to avoid extra copies. return x.(*adt.Num).X.Append(b, 'G'), nil case adt.StringKind: // Do not use json.Marshal as it escapes HTML. b2, err := internaljson.Marshal(x.(*adt.String).Str) return append(b, b2...), err case adt.BytesKind: b2, err := json.Marshal(x.(*adt.Bytes).B) return append(b, b2...), err case adt.ListKind: i := v.mustList(ctx) return listAppendJSON(b, &i) case adt.StructKind: obj, err := v.structValData(ctx) if err != nil { return nil, toMarshalErr(v, err) } return obj.appendJSON(b) case adt.BottomKind: return nil, toMarshalErr(v, x.(*adt.Bottom)) default: return nil, marshalErrf(v, x, 0, "cannot convert value %q of type %T to JSON", str(ctx, x), x) } } // Syntax converts the possibly partially evaluated value into syntax. This // can use used to print the value with package format. func (v Value) Syntax(opts ...Option) ast.Node { // TODO: the default should ideally be simplified representation that // exactly represents the value. The latter can currently only be // ensured with Raw(). if v.v == nil { return nil } o := getOptions(opts) p := export.Profile{ Simplify: !o.raw, TakeDefaults: o.final, ShowOptional: !o.omitOptional && !o.concrete, ShowDefinitions: !o.omitDefinitions && !o.concrete, ShowHidden: !o.omitHidden && !o.concrete, ShowAttributes: !o.omitAttrs, ShowDocs: o.docs, ShowErrors: o.showErrors, InlineImports: o.inlineImports, Fragment: o.raw, } pkgID := v.instance().ID() bad := func(name string, err error) ast.Node { const format = `"%s: internal error Error: %s Profile: %#v Value: %v You could file a bug with the above information at: https://cuelang.org/issues/new?assignees=&labels=NeedsInvestigation&template=bug_report.md&title=. ` cg := &ast.CommentGroup{Doc: true} msg := fmt.Sprintf(format, name, err, p, v) for _, line := range strings.Split(msg, "\n") { cg.List = append(cg.List, &ast.Comment{Text: "// " + line}) } x := &ast.BadExpr{} ast.AddComment(x, cg) return x } // var expr ast.Expr var err error var f *ast.File if o.concrete || o.final || o.resolveReferences { f, err = p.Vertex(v.idx, pkgID, v.v) if err != nil { return bad(`"cuelang.org/go/internal/core/export".Vertex`, err) } } else { p.AddPackage = true f, err = p.Def(v.idx, pkgID, v.v) if err != nil { return bad(`"cuelang.org/go/internal/core/export".Def`, err) } } outer: for _, d := range f.Decls { switch d.(type) { case *ast.Package, *ast.ImportDecl: return f case *ast.CommentGroup, *ast.Attribute: default: break outer } } if len(f.Decls) == 1 { if e, ok := f.Decls[0].(*ast.EmbedDecl); ok { for _, c := range ast.Comments(e) { ast.AddComment(f, c) } for _, c := range ast.Comments(e.Expr) { ast.AddComment(f, c) } ast.SetComments(e.Expr, f.Comments()) return e.Expr } } st := &ast.StructLit{ Elts: f.Decls, } ast.SetComments(st, f.Comments()) return st } // Doc returns all documentation comments associated with the field from which // the current value originates. func (v Value) Doc() []*ast.CommentGroup { if v.v == nil { return nil } return export.ExtractDoc(v.v) } // Source returns the original node for this value. The return value may not // be an [ast.Expr]. For instance, a struct kind may be represented by a // struct literal, a field comprehension, or a file. It returns nil for // computed nodes. Use [Value.Expr] to get all source values that apply to a field. func (v Value) Source() ast.Node { if v.v == nil { return nil } count := 0 var src ast.Node v.v.VisitLeafConjuncts(func(c adt.Conjunct) bool { src = c.Source() count++ return true }) if count > 1 || src == nil { src = v.v.Value().Source() } return src } // If v exactly represents a package, BuildInstance returns // the build instance corresponding to the value; otherwise it returns nil. // // The value returned by [Value.ReferencePath] will commonly represent a package. func (v Value) BuildInstance() *build.Instance { if v.idx == nil { return nil } return v.idx.GetInstanceFromNode(v.v) } // Err returns the error represented by v or nil v is not an error. func (v Value) Err() error { if err := v.checkKind(v.ctx(), adt.BottomKind); err != nil { return v.toErr(err) } return nil } // Pos returns position information. // // Use [Value.Expr] to get positions for all conjuncts and disjuncts. func (v Value) Pos() token.Pos { if v.v == nil { return token.NoPos } if src := v.Source(); src != nil { if pos := src.Pos(); pos != token.NoPos { return pos } } // Pick the most-concrete field. var p token.Pos v.v.VisitLeafConjuncts(func(c adt.Conjunct) bool { x := c.Elem() pp := pos(x) if pp == token.NoPos { return true } p = pp // Prefer struct conjuncts with actual fields. if s, ok := x.(*adt.StructLit); ok && len(s.Fields) > 0 { return false } return true }) return p } // TODO: IsFinal: this value can never be changed. // Allows reports whether a field with the given selector could be added to v. // // Allows does not take into account validators like list.MaxItems(4). This may // change in the future. func (v Value) Allows(sel Selector) bool { if v.v.HasEllipsis { return true } c := v.ctx() f := sel.sel.feature(c) return v.v.Accept(c, f) } // IsConcrete reports whether the current value is a concrete scalar value // (not relying on default values), a terminal error, a list, or a struct. // It does not verify that values of lists or structs are concrete themselves. // To check whether there is a concrete default, use this method on [Value.Default]. func (v Value) IsConcrete() bool { if v.v == nil { return false // any is neither concrete, not a list or struct. } w := v.v.DerefValue() if b := w.Bottom(); b != nil { return !b.IsIncomplete() } if !adt.IsConcrete(w) { return false } return true } // // Deprecated: IsIncomplete // // // // It indicates that the value cannot be fully evaluated due to // // insufficient information. // func (v Value) IsIncomplete() bool { // panic("deprecated") // } // Exists reports whether this value existed in the configuration. func (v Value) Exists() bool { if v.v == nil { return false } if err := v.v.Bottom(); err != nil { return !err.NotExists } return true } // isKind reports whether a value matches a particular kind. // It is like checkKind, except that it doesn't construct an error value. // Note that when v is bottom, the method always returns false. func (v Value) isKind(ctx *adt.OpContext, want adt.Kind) bool { if v.v == nil { return false } x := v.eval(ctx) if _, ok := x.(*adt.Bottom); ok { return false } k := x.Kind() if want != adt.BottomKind { if k&want == adt.BottomKind { return false } if !adt.IsConcrete(x) { return false } } return true } // checkKind returns a bottom error if a value does not match a particular kind, // describing the reason why. Note that when v is bottom, it is always returned as-is. func (v Value) checkKind(ctx *adt.OpContext, want adt.Kind) *adt.Bottom { if v.v == nil { return errNotExists } // TODO: use checkKind x := v.eval(ctx) if b, ok := x.(*adt.Bottom); ok { return b } k := x.Kind() if want != adt.BottomKind { if k&want == adt.BottomKind { return mkErr(x, "cannot use value %v (type %s) as %s", ctx.Str(x), k, want) } if !adt.IsConcrete(x) { return mkErr(x, adt.IncompleteError, "non-concrete value %v", k) } } return nil } func makeInt(v Value, x int64) Value { n := &adt.Num{K: adt.IntKind} n.X.SetInt64(int64(x)) return remakeFinal(v, n) } // Len returns the number of items of the underlying value. // For lists it reports the capacity of the list. For structs it indicates the // number of fields, for bytes the number of bytes. func (v Value) Len() Value { if v.v != nil { switch x := v.eval(v.ctx()).(type) { case *adt.Vertex: if x.IsList() { n := &adt.Num{K: adt.IntKind} n.X.SetInt64(int64(len(x.Elems()))) if x.IsClosedList() { return remakeFinal(v, n) } // Note: this HAS to be a Conjunction value and cannot be // an adt.BinaryExpr, as the expressions would be considered // to be self-contained and unresolvable when evaluated // (can never become concrete). c := &adt.Conjunction{Values: []adt.Value{ &adt.BasicType{K: adt.IntKind}, &adt.BoundValue{Op: adt.GreaterEqualOp, Value: n}, }} return remakeFinal(v, c) } case *adt.Bytes: return makeInt(v, int64(len(x.B))) case *adt.String: return makeInt(v, int64(len([]rune(x.Str)))) } } const msg = "len not supported for type %v" return remakeValue(v, nil, mkErr(v.v, msg, v.Kind())) } // Elem returns the value of undefined element types of lists and structs. // // Deprecated: use [Value.LookupPath] in combination with [AnyString] or [AnyIndex]. func (v hiddenValue) Elem() (Value, bool) { sel := AnyString if v.v.IsList() { sel = AnyIndex } x := v.LookupPath(MakePath(sel)) return x, x.Exists() } // List creates an iterator over the values of a list or reports an error if // v is not a list. func (v Value) List() (Iterator, error) { v, _ = v.Default() ctx := v.ctx() if err := v.checkKind(ctx, adt.ListKind); err != nil { return Iterator{idx: v.idx, ctx: ctx}, v.toErr(err) } return v.mustList(ctx), nil } // mustList is like [Value.List], but reusing ctx and leaving it to the caller // to apply defaults and check the kind. func (v Value) mustList(ctx *adt.OpContext) Iterator { arcs := []*adt.Vertex{} for _, a := range v.v.Elems() { if a.Label.IsInt() { arcs = append(arcs, a) } } return Iterator{idx: v.idx, ctx: ctx, val: v, arcs: arcs} } // Null reports an error if v is not null. func (v Value) Null() error { v, _ = v.Default() if err := v.checkKind(v.ctx(), adt.NullKind); err != nil { return v.toErr(err) } return nil } // IsNull reports whether v is null. func (v Value) IsNull() bool { v, _ = v.Default() return v.isKind(v.ctx(), adt.NullKind) } // Bool returns the bool value of v or false and an error if v is not a boolean. func (v Value) Bool() (bool, error) { v, _ = v.Default() ctx := v.ctx() if err := v.checkKind(ctx, adt.BoolKind); err != nil { return false, v.toErr(err) } return v.eval(ctx).(*adt.Bool).B, nil } // String returns the string value if v is a string or an error otherwise. func (v Value) String() (string, error) { v, _ = v.Default() ctx := v.ctx() if err := v.checkKind(ctx, adt.StringKind); err != nil { return "", v.toErr(err) } return v.eval(ctx).(*adt.String).Str, nil } // Bytes returns a byte slice if v represents a list of bytes or an error // otherwise. func (v Value) Bytes() ([]byte, error) { v, _ = v.Default() ctx := v.ctx() switch x := v.eval(ctx).(type) { case *adt.Bytes: return bytes.Clone(x.B), nil case *adt.String: return []byte(x.Str), nil } return nil, v.toErr(v.checkKind(ctx, adt.BytesKind|adt.StringKind)) } // Reader returns a new Reader if v is a string or bytes type and an error // otherwise. func (v hiddenValue) Reader() (io.Reader, error) { v, _ = v.Default() ctx := v.ctx() switch x := v.eval(ctx).(type) { case *adt.Bytes: return bytes.NewReader(x.B), nil case *adt.String: return strings.NewReader(x.Str), nil } return nil, v.toErr(v.checkKind(ctx, adt.StringKind|adt.BytesKind)) } // TODO: distinguish between optional, hidden, etc. Probably the best approach // is to mark options in context and have a single function for creating // a structVal. // structVal returns an structVal or an error if v is not a struct. func (v Value) structValData(ctx *adt.OpContext) (structValue, *adt.Bottom) { return v.structValOpts(ctx, options{ omitHidden: true, omitDefinitions: true, omitOptional: true, }) } // structVal returns an structVal or an error if v is not a struct. func (v Value) structValOpts(ctx *adt.OpContext, o options) (s structValue, err *adt.Bottom) { v, _ = v.Default() obj := v.v switch b := v.v.Bottom(); { case b != nil && b.IsIncomplete() && !o.concrete && !o.final: // Allow scalar values if hidden or definition fields are requested. case !o.omitHidden, !o.omitDefinitions: default: if err := v.checkKind(ctx, adt.StructKind); err != nil && !err.ChildError { return structValue{}, err } } // features are topologically sorted. // TODO(sort): make sort order part of the evaluator and eliminate this. features := export.VertexFeatures(ctx, obj) arcs := make([]*adt.Vertex, 0, len(obj.Arcs)) for _, f := range features { if f.IsLet() { continue } if f.IsDef() && (o.omitDefinitions || o.concrete) { continue } if f.IsHidden() && o.omitHidden { continue } arc := obj.LookupRaw(f) if arc == nil { continue } switch arc.ArcType { case adt.ArcOptional: if o.omitOptional { continue } case adt.ArcRequired: // We report an error for required fields if the configuration is // final or concrete. We also do so if omitOptional is true, as // it avoids hiding errors in required fields. if o.omitOptional || o.concrete || o.final { arc = &adt.Vertex{ Label: f, Parent: arc.Parent, Conjuncts: arc.Conjuncts, BaseValue: adt.NewRequiredNotPresentError(ctx, arc), } arc.ForceDone() } } arcs = append(arcs, arc) } return structValue{ctx, v, obj, arcs}, nil } // Struct returns the underlying struct of a value or an error if the value // is not a struct. // // Deprecated: use [Value.Fields]. func (v hiddenValue) Struct() (*Struct, error) { ctx := v.ctx() obj, err := v.structValOpts(ctx, options{}) if err != nil { return nil, v.toErr(err) } return &Struct{obj}, nil } // Struct represents a CUE struct value. // // Deprecated: only used by deprecated functions. type Struct struct { structValue } type hiddenStruct = Struct // FieldInfo contains information about a struct field. // // Deprecated: only used by deprecated functions. type FieldInfo struct { Selector string Name string // Deprecated: use [FieldInfo.Selector] Pos int Value Value SelectorType SelectorType IsDefinition bool IsOptional bool IsHidden bool } func (s *hiddenStruct) Len() int { return s.structValue.Len() } // field reports information about the ith field, i < o.Len(). func (s *hiddenStruct) Field(i int) FieldInfo { a := s.at(i) opt := a.ArcType == adt.ArcOptional selType := featureToSelType(a.Label, a.ArcType) ctx := s.v.ctx() v := makeChildValue(s.v, a) name := s.v.idx.LabelStr(a.Label) str := a.Label.SelectorString(ctx) return FieldInfo{str, name, i, v, selType, a.Label.IsDef(), opt, a.Label.IsHidden()} } // FieldByName looks up a field for the given name. If isIdent is true, it will // look up a definition or hidden field (starting with `_` or `_#`). Otherwise // it interprets name as an arbitrary string for a regular field. func (s *hiddenStruct) FieldByName(name string, isIdent bool) (FieldInfo, error) { f := s.v.idx.Label(name, isIdent) for i, a := range s.arcs { if a.Label == f { return s.Field(i), nil } } return FieldInfo{}, errNotFound } // Fields creates an iterator over the struct's fields. func (s *hiddenStruct) Fields(opts ...Option) *Iterator { iter, _ := s.v.Fields(opts...) return iter } // Fields creates an iterator over v's fields if v is a struct or an error // otherwise. func (v Value) Fields(opts ...Option) (*Iterator, error) { o := options{omitDefinitions: true, omitHidden: true, omitOptional: true} o.updateOptions(opts) ctx := v.ctx() obj, err := v.structValOpts(ctx, o) if err != nil { return &Iterator{idx: v.idx, ctx: ctx}, v.toErr(err) } return &Iterator{idx: v.idx, ctx: ctx, val: v, arcs: obj.arcs}, nil } // Lookup reports the value at a path starting from v. The empty path returns v // itself. // // [Value.Exists] can be used to verify if the returned value existed. // Lookup cannot be used to look up hidden or optional fields or definitions. // // Deprecated: use [Value.LookupPath]. At some point before v1.0.0, this method will // be removed to be reused eventually for looking up a selector. func (v hiddenValue) Lookup(path ...string) Value { ctx := v.ctx() for _, k := range path { // TODO(eval) TODO(error): always search in full data and change error // message if a field is found but is of the incorrect type. obj, err := v.structValData(ctx) if err != nil { // TODO: return a Value at the same location and a new error? return newErrValue(v, err) } v = obj.Lookup(k) } return v } // Path returns the path to this value from the root of an Instance. // // This is currently only defined for values that have a fixed path within // a configuration, and thus not those that are derived from Elem, Template, // or programmatically generated values such as those returned by Unify. func (v Value) Path() Path { if v.v == nil { return Path{} } return Path{path: appendPath(nil, v)} } // Path computes the sequence of Features leading from the root to of the // instance to this Vertex. func appendPath(a []Selector, v Value) []Selector { if p := v.parent(); p.v != nil { a = appendPath(a, p) } if v.v.Label == 0 { // A Label may be 0 for programmatically inserted nodes. return a } f := v.v.Label if index := f.Index(); index == adt.MaxIndex { return append(a, Selector{anySelector(f)}) } var sel selector switch t := f.Typ(); t { case adt.IntLabel: sel = indexSelector(f) case adt.DefinitionLabel: sel = definitionSelector(f.SelectorString(v.idx)) case adt.HiddenDefinitionLabel, adt.HiddenLabel: sel = scopedSelector{ name: f.IdentString(v.idx), pkg: f.PkgID(v.idx), } case adt.StringLabel: sel = stringSelector(f.StringValue(v.idx)) default: panic(fmt.Sprintf("unsupported label type %v", t)) } return append(a, Selector{sel}) } // LookupDef is equal to LookupPath(MakePath(Def(name))). // // Deprecated: use [Value.LookupPath]. func (v hiddenValue) LookupDef(name string) Value { return v.LookupPath(MakePath(Def(name))) } var errNotFound = errors.Newf(token.NoPos, "field not found") // FieldByName looks up a field for the given name. If isIdent is true, it will // look up a definition or hidden field (starting with `_` or `_#`). Otherwise // it interprets name as an arbitrary string for a regular field. // // Deprecated: use [Value.LookupPath]. func (v hiddenValue) FieldByName(name string, isIdent bool) (f FieldInfo, err error) { s, err := v.Struct() if err != nil { return f, err } return s.FieldByName(name, isIdent) } // LookupField reports information about a field of v. // // Deprecated: use [Value.LookupPath]. func (v hiddenValue) LookupField(name string) (FieldInfo, error) { s, err := v.Struct() if err != nil { // TODO: return a Value at the same location and a new error? return FieldInfo{}, err } f, err := s.FieldByName(name, true) if err != nil { return f, err } if f.IsHidden { return f, errNotFound } return f, err } // TODO: expose this API? // // // EvalExpr evaluates an expression within the scope of v, which must be // // a struct. // // // // Expressions may refer to builtin packages if they can be uniquely identified. // func (v Value) EvalExpr(expr ast.Expr) Value { // ctx := v.ctx() // result := evalExpr(ctx, v.eval(ctx), expr) // return newValueRoot(ctx, result) // } // Fill creates a new value by unifying v with the value of x at the given path. // // Values may be any Go value that can be converted to CUE, an ast.Expr or // a Value. In the latter case, it will panic if the Value is not from the same // Runtime. // // Any reference in v referring to the value at the given path will resolve // to x in the newly created value. The resulting value is not validated. // // Deprecated: use [Value.FillPath]. func (v hiddenValue) Fill(x interface{}, path ...string) Value { if v.v == nil { return v } selectors := make([]Selector, len(path)) for i, p := range path { selectors[i] = Str(p) } return v.FillPath(MakePath(selectors...), x) } // FillPath creates a new value by unifying v with the value of x at the given // path. // // If x is an [ast.Expr], it will be evaluated within the context of the // given path: identifiers that are not resolved within the expression are // resolved as if they were defined at the path position. // // If x is a Value, it will be used as is. It panics if x is not created // from the same [Context] as v. // // Otherwise, the given Go value will be converted to CUE using the same rules // as [Context.Encode]. // // Any reference in v referring to the value at the given path will resolve to x // in the newly created value. The resulting value is not validated. func (v Value) FillPath(p Path, x interface{}) Value { if v.v == nil { // TODO: panic here? return v } ctx := v.ctx() if err := p.Err(); err != nil { return newErrValue(v, mkErr(nil, 0, "invalid path: %v", err)) } var expr adt.Expr switch x := x.(type) { case Value: if v.idx != x.idx { panic("values are not from the same runtime") } expr = x.v case ast.Expr: n := getScopePrefix(v, p) // TODO: inject import path of current package? expr = resolveExpr(ctx, n, x) default: expr = convert.GoValueToValue(ctx, x, true) } for i := len(p.path) - 1; i >= 0; i-- { switch sel := p.path[i]; sel.Type() { case StringLabel | PatternConstraint: expr = &adt.StructLit{Decls: []adt.Decl{ &adt.BulkOptionalField{ Filter: &adt.BasicType{K: adt.StringKind}, Value: expr, }, }} case IndexLabel | PatternConstraint: expr = &adt.ListLit{Elems: []adt.Elem{ &adt.Ellipsis{Value: expr}, }} case IndexLabel: i := sel.Index() list := &adt.ListLit{} any := &adt.Top{} // TODO(perf): make this a constant thing. This will be possible with the query extension. for range i { list.Elems = append(list.Elems, any) } list.Elems = append(list.Elems, expr, &adt.Ellipsis{}) expr = list default: f := &adt.Field{ Label: sel.sel.feature(v.idx), Value: expr, ArcType: adt.ArcMember, } switch sel.ConstraintType() { case OptionalConstraint: f.ArcType = adt.ArcOptional case RequiredConstraint: f.ArcType = adt.ArcRequired } expr = &adt.StructLit{Decls: []adt.Decl{f}} } } n := &adt.Vertex{} n.AddConjunct(adt.MakeRootConjunct(nil, expr)) n.Finalize(ctx) w := makeValue(v.idx, n, v.parent_) return v.Unify(w) } // Template returns a function that represents the template definition for a // struct in a configuration file. It returns nil if v is not a struct kind or // if there is no template associated with the struct. // // The returned function returns the value that would be unified with field // given its name. // // Deprecated: use [Value.LookupPath] in combination with using optional selectors. func (v hiddenValue) Template() func(label string) Value { if v.v == nil { return nil } // Implementation for the old evaluator. types := v.v.OptionalTypes() switch { case types&(adt.HasAdditional|adt.HasPattern) != 0: case v.v.PatternConstraints != nil: default: return nil } return func(label string) Value { return v.LookupPath(MakePath(Str(label).Optional())) } } // Subsume reports nil when w is an instance of v or an error otherwise. // // Without options, the entire value is considered for assumption, which means // Subsume tests whether v is a backwards compatible (newer) API version of w. // // Use the [Final] option to check subsumption if a w is known to be final, and // should assumed to be closed. // // Use the [Raw] option to do a low-level subsumption, taking defaults into // account. // // Value v and w must be obtained from the same build. TODO: remove this // requirement. func (v Value) Subsume(w Value, opts ...Option) error { o := getOptions(opts) p := subsume.CUE switch { case o.final && o.ignoreClosedness: p = subsume.FinalOpen case o.final: p = subsume.Final case o.ignoreClosedness: p = subsume.API } if !o.raw { p.Defaults = true } ctx := v.ctx() return p.Value(ctx, v.v, w.v) } // TODO: this is likely not correct for V3. There are some cases where this is // still used for V3. Transition away from those. func allowed(ctx *adt.OpContext, parent, n *adt.Vertex) *adt.Bottom { if !parent.IsClosedList() && !parent.IsClosedStruct() { return nil } for _, a := range n.Arcs { if !parent.Accept(ctx, a.Label) { defer ctx.PopArc(ctx.PushArc(parent)) label := a.Label.SelectorString(ctx) parent.Accept(ctx, a.Label) return ctx.NewErrf("field not allowed: %s", label) } } return nil } func addConjuncts(ctx *adt.OpContext, dst, src *adt.Vertex) { c := adt.MakeRootConjunct(nil, src) c.CloseInfo.GroupUnify = true if src.ClosedRecursive { if ctx.Version == internal.EvalV2 { var root adt.CloseInfo c.CloseInfo = root.SpawnRef(src, src.ClosedRecursive, nil) } else { c.CloseInfo.FromDef = true } } dst.AddConjunct(c) } // Unify reports the greatest lower bound of v and w. // // Value v and w must be obtained from the same build. // TODO: remove this requirement. func (v Value) Unify(w Value) Value { if v.v == nil { return w } if w.v == nil || w.v == v.v { return v } ctx := v.ctx() n := &adt.Vertex{} addConjuncts(ctx, n, v.v) addConjuncts(ctx, n, w.v) n.Finalize(ctx) n.Parent = v.v.Parent n.Label = v.v.Label n.ClosedRecursive = v.v.ClosedRecursive || w.v.ClosedRecursive if err := n.Err(ctx); err != nil { return makeValue(v.idx, n, v.parent_) } if ctx.Version == internal.EvalV2 { if err := allowed(ctx, v.v, n); err != nil { return newErrValue(w, err) } if err := allowed(ctx, w.v, n); err != nil { return newErrValue(v, err) } } return makeValue(v.idx, n, v.parent_) } // UnifyAccept is like [Value.Unify](w), but will disregard the closedness rules for // v and w, and will, instead, only allow fields that are present in accept. // // UnifyAccept is used to piecemeal unify individual conjuncts obtained from // accept without violating closedness rules. func (v Value) UnifyAccept(w Value, accept Value) Value { if v.v == nil { return w } if w.v == nil { return v } if accept.v == nil { panic("accept must exist") } n := &adt.Vertex{} ctx := v.ctx() cv := adt.MakeRootConjunct(nil, v.v) cw := adt.MakeRootConjunct(nil, w.v) switch ctx.Version { case internal.EvalV2: n.AddConjunct(cv) n.AddConjunct(cw) n.Finalize(ctx) n.Parent = v.v.Parent n.Label = v.v.Label if err := n.Err(ctx); err != nil { return makeValue(v.idx, n, v.parent_) } if err := allowed(ctx, accept.v, n); err != nil { return newErrValue(accept, err) } case internal.EvalV3: cv.CloseInfo.FromEmbed = true cw.CloseInfo.FromEmbed = true n.AddConjunct(cv) n.AddConjunct(cw) ca := adt.MakeRootConjunct(nil, accept.v) n.AddConjunct(ca) n.Finalize(ctx) } return makeValue(v.idx, n, v.parent_) } // Equals reports whether two values are equal, ignoring optional fields. // The result is undefined for incomplete values. func (v Value) Equals(other Value) bool { if v.v == nil || other.v == nil { return false } return adt.Equal(v.ctx(), v.v, other.v, 0) } func (v Value) instance() *Instance { if v.v == nil { return nil } return getImportFromNode(v.idx, v.v) } // Reference returns the instance and path referred to by this value such that // inst.Lookup(path) resolves to the same value, or no path if this value is not // a reference. If a reference contains index selection (foo[bar]), it will // only return a reference if the index resolves to a concrete value. // // Deprecated: use [Value.ReferencePath] func (v hiddenValue) Reference() (inst *Instance, path []string) { root, p := v.ReferencePath() if !root.Exists() { return nil, nil } inst = getImportFromNode(v.idx, root.v) for _, sel := range p.Selectors() { switch x := sel.sel.(type) { case stringSelector: path = append(path, string(x)) default: path = append(path, sel.String()) } } return inst, path } // ReferencePath returns the value and path referred to by this value such that // [Value.LookupPath](path) resolves to the same value, or no path if this value // is not a reference. func (v Value) ReferencePath() (root Value, p Path) { // TODO: don't include references to hidden fields. c, count := v.v.SingleConjunct() if count != 1 { return Value{}, Path{} } ctx := v.ctx() env, expr := c.EnvExpr() x, path := reference(v.idx, ctx, env, expr) if x == nil { return Value{}, Path{} } // NOTE: due to structure sharing, the path of the referred node may end // up different from the one explicitly pointed to. The value will be the // same, but the scope may differ. // TODO(structureshare): see if we can construct the original path. This // only has to be done if structures are being shared. return makeValue(v.idx, x, nil), Path{path: path} } func reference(rt *runtime.Runtime, c *adt.OpContext, env *adt.Environment, r adt.Expr) (inst *adt.Vertex, path []Selector) { ctx := c defer ctx.PopState(ctx.PushState(env, r.Source())) switch x := r.(type) { // TODO: do we need to handle Vertex as well, in case this is hard-wired? // Probably not, as this results from dynamic content. case *adt.NodeLink: // TODO: consider getting rid of NodeLink. inst, path = mkPath(rt, nil, x.Node) case *adt.FieldReference: env := ctx.Env(x.UpCount) inst, path = mkPath(rt, nil, env.Vertex) path = appendSelector(path, featureToSel(x.Label, rt)) case *adt.LabelReference: env := ctx.Env(x.UpCount) return mkPath(rt, nil, env.Vertex) case *adt.DynamicReference: env := ctx.Env(x.UpCount) inst, path = mkPath(rt, nil, env.Vertex) v, _ := ctx.Evaluate(env, x.Label) path = appendSelector(path, valueToSel(v)) case *adt.ImportReference: inst = rt.LoadImport(rt.LabelStr(x.ImportPath)) case *adt.SelectorExpr: inst, path = reference(rt, c, env, x.X) path = appendSelector(path, featureToSel(x.Sel, rt)) case *adt.IndexExpr: inst, path = reference(rt, c, env, x.X) v, _ := ctx.Evaluate(env, x.Index) path = appendSelector(path, valueToSel(v)) } if inst == nil { return nil, nil } return inst, path } func mkPath(r *runtime.Runtime, a []Selector, v *adt.Vertex) (root *adt.Vertex, path []Selector) { if v.Parent == nil { return v, a } root, path = mkPath(r, a, v.Parent) path = appendSelector(path, featureToSel(v.Label, r)) return root, path } type options struct { concrete bool // enforce that values are concrete raw bool // show original values hasHidden bool omitHidden bool omitDefinitions bool omitOptional bool omitAttrs bool inlineImports bool resolveReferences bool showErrors bool final bool ignoreClosedness bool // used for comparing APIs docs bool disallowCycles bool // implied by concrete } // An Option defines modes of evaluation. type Option option type option func(p *options) // Final indicates a value is final. It implicitly closes all structs and lists // in a value and selects defaults. func Final() Option { return func(o *options) { o.final = true o.omitDefinitions = true o.omitOptional = true o.omitHidden = true } } // Schema specifies the input is a Schema. Used by Subsume. func Schema() Option { return func(o *options) { o.ignoreClosedness = true } } // Concrete ensures that all values are concrete. // // For [Validate] this means it returns an error if this is not the case. // In other cases a non-concrete value will be replaced with an error. func Concrete(concrete bool) Option { return func(p *options) { if concrete { p.concrete = true p.final = true if !p.hasHidden { p.omitHidden = true p.omitDefinitions = true } } } } // InlineImports causes references to values within imported packages to be // inlined. References to builtin packages are not inlined. func InlineImports(expand bool) Option { return func(p *options) { p.inlineImports = expand } } // DisallowCycles forces validation in the presence of cycles, even if // non-concrete values are allowed. This is implied by [Concrete]. func DisallowCycles(disallow bool) Option { return func(p *options) { p.disallowCycles = disallow } } // ResolveReferences forces the evaluation of references when outputting. // // Deprecated: [Value.Syntax] will now always attempt to resolve dangling references and // make the output self-contained. When [Final] or [Concrete] are used, // it will already attempt to resolve all references. // See also [InlineImports]. func ResolveReferences(resolve bool) Option { return func(p *options) { p.resolveReferences = resolve // ResolveReferences is implemented as a Value printer, rather than // a definition printer, even though it should be more like the latter. // To reflect this we convert incomplete errors to their original // expression. // // TODO: ShowErrors mostly shows incomplete errors, even though this is // just an approximation. There seems to be some inconsistencies as to // when child errors are marked as such, making the conversion somewhat // inconsistent. This option is conservative, though. p.showErrors = true } } // ErrorsAsValues treats errors as a regular value, including them at the // location in the tree where they occur, instead of interpreting them as a // configuration-wide failure that is returned instead of root value. // Used by Syntax. func ErrorsAsValues(show bool) Option { return func(p *options) { p.showErrors = show } } // Raw tells Syntax to generate the value as is without any simplifications and // without ensuring a value is self contained. Any references are left dangling. // The generated syntax tree can be compiled by passing the Value from which it // was generated to scope. // // The option InlineImports overrides this option with respect to ensuring the // output is self contained. func Raw() Option { return func(p *options) { p.raw = true } } // All indicates that all fields and values should be included in processing // even if they can be elided or omitted. func All() Option { return func(p *options) { p.omitAttrs = false p.omitHidden = false p.omitDefinitions = false p.omitOptional = false } } // Docs indicates whether docs should be included. func Docs(include bool) Option { return func(p *options) { p.docs = true } } // Definitions indicates whether definitions should be included. // // Definitions may still be included for certain functions if they are referred // to by other values. func Definitions(include bool) Option { return func(p *options) { p.hasHidden = true p.omitDefinitions = !include } } // Hidden indicates that definitions and hidden fields should be included. func Hidden(include bool) Option { return func(p *options) { p.hasHidden = true p.omitHidden = !include p.omitDefinitions = !include } } // Optional indicates that optional fields should be included. func Optional(include bool) Option { return func(p *options) { p.omitOptional = !include } } // Attributes indicates that attributes should be included. func Attributes(include bool) Option { return func(p *options) { p.omitAttrs = !include } } func getOptions(opts []Option) (o options) { o.updateOptions(opts) return } func (o *options) updateOptions(opts []Option) { for _, fn := range opts { fn(o) } } // Validate reports any errors, recursively. The returned error may represent // more than one error, retrievable with [errors.Errors], if more than one // exists. // // Note that by default not all errors are reported, unless options like // [Concrete] are used. The [Final] option can be used to check for missing // required fields. func (v Value) Validate(opts ...Option) error { o := options{} o.updateOptions(opts) cfg := &validate.Config{ Concrete: o.concrete, Final: o.final, DisallowCycles: o.disallowCycles, AllErrors: true, } b := validate.Validate(v.ctx(), v.v, cfg) if b != nil { return v.toErr(b) } return nil } // Walk descends into all values of v, calling f. If f returns false, Walk // will not descent further. It only visits values that are part of the data // model, so this excludes definitions and optional, required, and hidden // fields. func (v Value) Walk(before func(Value) bool, after func(Value)) { ctx := v.ctx() switch v.Kind() { case StructKind: if before != nil && !before(v) { return } obj, _ := v.structValOpts(ctx, options{ omitHidden: true, omitDefinitions: true, }) for i := range obj.Len() { _, v := obj.At(i) // TODO: should we error on required fields, or visit them anyway? // Walk is not designed to error at this moment, though. if v.v.ArcType != adt.ArcMember { continue } v.Walk(before, after) } case ListKind: if before != nil && !before(v) { return } list, _ := v.List() for list.Next() { list.Value().Walk(before, after) } default: if before != nil { before(v) } } if after != nil { after(v) } } // Expr reports the operation of the underlying expression and the values it // operates on. // // For unary expressions, it returns the single value of the expression. // // For binary expressions it returns first the left and right value, in that // order. For associative operations however, (for instance '&' and '|'), it may // return more than two values, where the operation is to be applied in // sequence. // // For selector and index expressions it returns the subject and then the index. // For selectors, the index is the string value of the identifier. // // For interpolations it returns a sequence of values to be concatenated, some // of which will be literal strings and some unevaluated expressions. // // A builtin call expression returns the value of the builtin followed by the // args of the call. func (v Value) Expr() (Op, []Value) { // TODO: return v if this is complete? Yes for now if v.v == nil { return NoOp, nil } var expr adt.Expr var env *adt.Environment if v.v.IsData() { expr = v.v.Value() goto process } switch c, count := v.v.SingleConjunct(); count { case 0: if v.v.BaseValue == nil { return NoOp, []Value{makeValue(v.idx, v.v, v.parent_)} // TODO: v? } expr = v.v.Value() case 1: // the default case, processed below. env, expr = c.EnvExpr() if w, ok := expr.(*adt.Vertex); ok { return Value{v.idx, w, v.parent_}.Expr() } default: a := []Value{} ctx := v.ctx() v.v.VisitLeafConjuncts(func(c adt.Conjunct) bool { // Keep parent here. TODO: do we need remove the requirement // from other conjuncts? n := &adt.Vertex{ Parent: v.v.Parent, Label: v.v.Label, } n.AddConjunct(c) n.Finalize(ctx) a = append(a, makeValue(v.idx, n, v.parent_)) return true }) return adt.AndOp, a } process: // TODO: replace appends with []Value{}. For not leave. a := []Value{} op := NoOp switch x := expr.(type) { case *adt.BinaryExpr: a = append(a, remakeValue(v, env, x.X)) a = append(a, remakeValue(v, env, x.Y)) op = x.Op case *adt.UnaryExpr: a = append(a, remakeValue(v, env, x.X)) op = x.Op case *adt.BoundExpr: a = append(a, remakeValue(v, env, x.Expr)) op = x.Op case *adt.BoundValue: a = append(a, remakeValue(v, env, x.Value)) op = x.Op case *adt.Conjunction: // pre-expanded unification for _, conjunct := range x.Values { a = append(a, remakeValue(v, env, conjunct)) } op = AndOp case *adt.Disjunction: count := 0 outer: for i, disjunct := range x.Values { if i < x.NumDefaults { for _, n := range x.Values[x.NumDefaults:] { if subsume.Simplify.Value(v.ctx(), n, disjunct) == nil { continue outer } } } count++ a = append(a, remakeValue(v, env, disjunct)) } if count > 1 { op = OrOp } case *adt.DisjunctionExpr: // Filter defaults that are subsumed by another value. count := 0 outerExpr: for _, disjunct := range x.Values { if disjunct.Default { for _, n := range x.Values { a := adt.Vertex{ Label: v.v.Label, } b := a a.AddConjunct(adt.MakeRootConjunct(env, n.Val)) b.AddConjunct(adt.MakeRootConjunct(env, disjunct.Val)) ctx := v.ctx() a.Finalize(ctx) b.Finalize(ctx) if allowed(ctx, v.v, &b) != nil { // Everything subsumed bottom continue outerExpr } if allowed(ctx, v.v, &a) != nil { // An error doesn't subsume anything except another error. continue } a.Parent = v.v.Parent if !n.Default && subsume.Simplify.Value(ctx, &a, &b) == nil { continue outerExpr } } } count++ a = append(a, remakeValue(v, env, disjunct.Val)) } if count > 1 { op = adt.OrOp } case *adt.Interpolation: for _, p := range x.Parts { a = append(a, remakeValue(v, env, p)) } op = InterpolationOp case *adt.FieldReference: // TODO: allow hard link ctx := v.ctx() f := ctx.PushState(env, x.Src) env := ctx.Env(x.UpCount) a = append(a, remakeValue(v, nil, &adt.NodeLink{Node: env.Vertex})) a = append(a, remakeValue(v, nil, ctx.NewString(x.Label.SelectorString(ctx)))) _ = ctx.PopState(f) op = SelectorOp case *adt.SelectorExpr: a = append(a, remakeValue(v, env, x.X)) // A string selector is quoted. a = append(a, remakeValue(v, env, &adt.String{ Str: x.Sel.SelectorString(v.idx), })) op = SelectorOp case *adt.IndexExpr: a = append(a, remakeValue(v, env, x.X)) a = append(a, remakeValue(v, env, x.Index)) op = IndexOp case *adt.SliceExpr: a = append(a, remakeValue(v, env, x.X)) a = append(a, remakeValue(v, env, x.Lo)) a = append(a, remakeValue(v, env, x.Hi)) op = SliceOp case *adt.CallExpr: // Interpret "and" and "or" builtin semantically. if fn, ok := x.Fun.(*adt.Builtin); ok && len(x.Args) == 1 && (fn.Name == "or" || fn.Name == "and") { iter, _ := remakeValue(v, env, x.Args[0]).List() for iter.Next() { a = append(a, iter.Value()) } op = OrOp if fn.Name == "and" { op = AndOp } if len(a) == 0 { // Mimic semantics of builtin. switch op { case AndOp: a = append(a, remakeValue(v, env, &adt.Top{})) case OrOp: a = append(a, remakeValue(v, env, &adt.Bottom{ Code: adt.IncompleteError, Err: errors.Newf(x.Src.Fun.Pos(), "empty list in call to or"), })) } op = NoOp } break } a = append(a, remakeValue(v, env, x.Fun)) for _, arg := range x.Args { a = append(a, remakeValue(v, env, arg)) } op = CallOp case *adt.BuiltinValidator: a = append(a, remakeValue(v, env, x.Builtin)) for _, arg := range x.Args { a = append(a, remakeValue(v, env, arg)) } op = CallOp case *adt.StructLit: hasEmbed := false fields := []adt.Decl{} for _, d := range x.Decls { switch d.(type) { default: fields = append(fields, d) case adt.Value: fields = append(fields, d) case adt.Expr: hasEmbed = true } } if !hasEmbed { a = append(a, v) break } ctx := v.ctx() n := v.v if len(fields) > 0 { n = &adt.Vertex{ Parent: v.v.Parent, Label: v.v.Label, } s := &adt.StructLit{} if k := v.v.Kind(); k != adt.StructKind && k != BottomKind { // TODO: we should also add such a declaration for embeddings // of structs with definitions. However, this is currently // also not supported at the CUE level. If we do, it may be // best handled with a special mode of unification. s.Decls = append(s.Decls, &adt.BasicType{K: k}) } s.Decls = append(s.Decls, fields...) c := adt.MakeRootConjunct(env, s) n.AddConjunct(c) n.Finalize(ctx) n.Parent = v.v.Parent } // Simulate old embeddings. envEmbed := &adt.Environment{ Up: env, Vertex: n, } for _, d := range x.Decls { switch x := d.(type) { case adt.Value: case adt.Expr: // embedding n := &adt.Vertex{Label: v.v.Label} c := adt.MakeRootConjunct(envEmbed, x) n.AddConjunct(c) n.Finalize(ctx) n.Parent = v.v.Parent a = append(a, makeValue(v.idx, n, v.parent_)) } } // Could be done earlier, but keep struct with fields at end. if len(fields) > 0 { a = append(a, makeValue(v.idx, n, v.parent_)) } if len(a) == 1 { return a[0].Expr() } op = adt.AndOp default: a = append(a, v) } return op, a } cue-lang-cue-db9cc73/cue/types_test.go000066400000000000000000002224621474664451600200160ustar00rootroot00000000000000// Copyright 2018 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "bytes" "fmt" "io" "math" "math/big" "reflect" "strconv" "strings" "testing" "github.com/google/go-cmp/cmp" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/internal/astinternal" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/debug" "cuelang.org/go/internal/cuetdtest" "cuelang.org/go/internal/cuetest" "cuelang.org/go/internal/tdtest" ) func getValue(m *cuetdtest.M, body string) cue.Value { return m.CueContext().CompileString(body, cue.Filename("test")) } func mustCompile(t testing.TB, ctx *cue.Context, body string) cue.Value { t.Helper() val := ctx.CompileString(body, cue.Filename("test")) if err := val.Err(); err != nil { t.Fatal(err) } return val } func TestAPI(t *testing.T) { testCases := []struct { input string fun func(i cue.Value) cue.Value want string skip bool }{{ // Issue #567 input: ` #runSpec: {action: foo: int} v: {ction: foo: 1} `, fun: func(i cue.Value) cue.Value { runSpec := i.LookupDef("#runSpec") v := i.Lookup("v") res := runSpec.Unify(v) return res }, want: "_|_ // #runSpec.ction: field not allowed", skip: true, }, { // Issue #567 input: ` #runSpec: {action: foo: int} v: {action: Foo: 1} `, fun: func(i cue.Value) cue.Value { runSpec := i.LookupDef("#runSpec") v := i.Lookup("v") res := runSpec.Unify(v) return res }, want: "_|_ // #runSpec.action.Foo: field not allowed", }, { input: ` #runSpec: v: {action: foo: int} w: {ction: foo: 1} `, fun: func(i cue.Value) cue.Value { runSpec := i.LookupDef("#runSpec") v := runSpec.Lookup("v") w := i.Lookup("w") res := w.Unify(v) return res }, want: "_|_ // w.ction: field not allowed", }, { // Issue #1879 input: ` #Steps: { ... } test: #Steps & { if true { test1: "test1" } if false { test2: "test2" } } `, fun: func(v cue.Value) (val cue.Value) { sub := v.LookupPath(cue.ParsePath("test")) st, err := sub.Struct() if err != nil { panic(err) } for i := 0; i < st.Len(); i++ { val = st.Field(i).Value } return val }, want: `"test1"`, }} for _, tc := range testCases { if tc.skip { continue } cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() valIn := mustCompile(t, ctx, tc.input) valOut := tc.fun(valIn) got := fmt.Sprintf("%+v", valOut) if got != tc.want { t.Errorf("got:\n%s\nwant:\n%s", got, tc.want) } }) } } func TestValueType(t *testing.T) { testCases := []struct { value string kind cue.Kind incompleteKind cue.Kind json string valid bool concrete bool closed bool // pos token.Pos }{{ // Not a concrete value. value: `v: _`, kind: cue.BottomKind, incompleteKind: cue.TopKind, }, { value: `v: _|_`, kind: cue.BottomKind, incompleteKind: cue.BottomKind, concrete: true, }, { value: `v: 1&2`, kind: cue.BottomKind, incompleteKind: cue.BottomKind, concrete: true, }, { value: `v: b, b: 1&2`, kind: cue.BottomKind, incompleteKind: cue.BottomKind, concrete: true, }, { value: `v: (b[a]), b: 1, a: 1`, kind: cue.BottomKind, incompleteKind: cue.BottomKind, concrete: true, }, { // TODO: should be error{ value: `v: (b) b: bool`, kind: cue.BottomKind, incompleteKind: cue.BoolKind, }, { value: `v: ([][b]), b: "d"`, kind: cue.BottomKind, incompleteKind: cue.BottomKind, concrete: true, }, { value: `v: null`, kind: cue.NullKind, incompleteKind: cue.NullKind, concrete: true, }, { value: `v: true`, kind: cue.BoolKind, incompleteKind: cue.BoolKind, concrete: true, }, { value: `v: false`, kind: cue.BoolKind, incompleteKind: cue.BoolKind, concrete: true, }, { value: `v: bool`, kind: cue.BottomKind, incompleteKind: cue.BoolKind, }, { value: `v: 2`, kind: cue.IntKind, incompleteKind: cue.IntKind, concrete: true, }, { value: `v: 2.0`, kind: cue.FloatKind, incompleteKind: cue.FloatKind, concrete: true, }, { value: `v: 2.0Mi`, kind: cue.IntKind, incompleteKind: cue.IntKind, concrete: true, }, { value: `v: 14_000`, kind: cue.IntKind, incompleteKind: cue.IntKind, concrete: true, }, { value: `v: >=0 & <5`, kind: cue.BottomKind, incompleteKind: cue.NumberKind, }, { value: `v: float`, kind: cue.BottomKind, incompleteKind: cue.FloatKind, }, { value: `v: "str"`, kind: cue.StringKind, incompleteKind: cue.StringKind, concrete: true, }, { value: "v: '''\n'''", kind: cue.BytesKind, incompleteKind: cue.BytesKind, concrete: true, }, { value: "v: string", kind: cue.BottomKind, incompleteKind: cue.StringKind, }, { value: `v: {}`, kind: cue.StructKind, incompleteKind: cue.StructKind, concrete: true, }, { value: `v: close({})`, kind: cue.StructKind, incompleteKind: cue.StructKind, concrete: true, }, { value: `v: []`, kind: cue.ListKind, incompleteKind: cue.ListKind, concrete: true, }, { value: `v: [...int]`, kind: cue.ListKind, incompleteKind: cue.ListKind, concrete: true, }, { value: `v: {a: int, b: [1][a]}.b`, kind: cue.BottomKind, concrete: false, }, { value: `import "time" v: time.Time`, kind: cue.BottomKind, incompleteKind: cue.StringKind, concrete: false, }, { value: `import "time" v: {a: time.Time}.a`, kind: cue.BottomKind, incompleteKind: cue.StringKind, concrete: false, }, { value: `import "time" v: {a: time.Time & string}.a`, kind: cue.BottomKind, incompleteKind: cue.StringKind, concrete: false, }, { value: `import "strings" v: {a: strings.ContainsAny("D")}.a`, kind: cue.BottomKind, incompleteKind: cue.StringKind, concrete: false, }, { value: `import "struct" v: {a: struct.MaxFields(2) & {}}.a`, kind: cue.StructKind, // Can determine a valid struct already. incompleteKind: cue.StructKind, concrete: true, }, { value: `v: #Foo #Foo: { name: string, ... }`, kind: cue.StructKind, incompleteKind: cue.StructKind, concrete: true, }, { value: `v: #Foo #Foo: { name: string, }`, kind: cue.StructKind, incompleteKind: cue.StructKind, concrete: true, }, { value: `v: #Foo | int #Foo: { name: string, }`, incompleteKind: cue.StructKind | cue.IntKind, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { val := getValue(m, tc.value) v := val.Lookup("v") if got := v.Kind(); got != tc.kind { t.Errorf("Kind: got %x; want %x", int(got), int(tc.kind)) } want := tc.incompleteKind | cue.BottomKind if got := v.IncompleteKind(); got != want { t.Errorf("IncompleteKind: got %x; want %x", int(got), int(want)) } if got := v.IsConcrete(); got != tc.concrete { t.Errorf("IsConcrete: got %v; want %v", got, tc.concrete) } }) } } func TestInt(t *testing.T) { testCases := []struct { value string int int64 uint uint64 base int err string errU string notInt bool }{{ value: "1", int: 1, uint: 1, }, { value: "-1", int: -1, uint: 0, errU: cue.ErrAbove.Error(), }, { value: "-111222333444555666777888999000", int: math.MinInt64, uint: 0, err: cue.ErrAbove.Error(), errU: cue.ErrAbove.Error(), }, { value: "111222333444555666777888999000", int: math.MaxInt64, uint: math.MaxUint64, err: cue.ErrBelow.Error(), errU: cue.ErrBelow.Error(), }, { value: "1.0", err: "cannot use value 1.0 (type float) as int", errU: "cannot use value 1.0 (type float) as int", notInt: true, }, { value: "int", err: "non-concrete value int", errU: "non-concrete value int", notInt: true, }, { value: "_|_", err: "explicit error (_|_ literal) in source", errU: "explicit error (_|_ literal) in source", notInt: true, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { n := getValue(m, tc.value) base := 10 if tc.base > 0 { base = tc.base } b, err := n.AppendInt(nil, base) if checkFailed(t, err, tc.err, "append") { want := tc.value if got := string(b); got != want { t.Errorf("append: got %v; want %v", got, want) } } vi, err := n.Int64() checkErr(t, err, tc.err, "Int64") if vi != tc.int { t.Errorf("Int64: got %v; want %v", vi, tc.int) } vu, err := n.Uint64() checkErr(t, err, tc.errU, "Uint64") if vu != uint64(tc.uint) { t.Errorf("Uint64: got %v; want %v", vu, tc.uint) } }) } } func TestFloat(t *testing.T) { testCases := []struct { value string float string float64 float64 mant string exp int fmt byte prec int kind cue.Kind err string }{{ value: "1", float: "1", mant: "1", exp: 0, float64: 1, fmt: 'g', kind: cue.IntKind, }, { value: "-1", float: "-1", mant: "-1", exp: 0, float64: -1, fmt: 'g', kind: cue.IntKind, }, { value: "0.0", float: "0.0", mant: "0", exp: -1, float64: 0.0, fmt: 'g', kind: cue.FloatKind, }, { value: "1.0", float: "1.0", mant: "10", exp: -1, float64: 1.0, fmt: 'g', kind: cue.FloatKind, }, { value: "2.6", float: "2.6", mant: "26", exp: -1, float64: 2.6, fmt: 'g', kind: cue.FloatKind, }, { value: "20.600", float: "20.60", mant: "20600", exp: -3, float64: 20.60, prec: 2, fmt: 'f', kind: cue.FloatKind, }, { value: "1/0", float: "", float64: 0, prec: 2, fmt: 'f', err: "division by zero", kind: cue.BottomKind, }, { value: "1.797693134862315708145274237317043567982e+308", float: "1.8e+308", mant: "1797693134862315708145274237317043567982", exp: 269, float64: math.Inf(1), prec: 2, fmt: 'g', err: cue.ErrAbove.Error(), kind: cue.FloatKind, }, { value: "-1.797693134862315708145274237317043567982e+308", float: "-1.8e+308", mant: "-1797693134862315708145274237317043567982", exp: 269, float64: math.Inf(-1), prec: 2, fmt: 'g', kind: cue.FloatKind, err: cue.ErrBelow.Error(), }, { value: "4.940656458412465441765687928682213723650e-324", float: "4.941e-324", mant: "4940656458412465441765687928682213723650", exp: -363, float64: 0, prec: 4, fmt: 'g', kind: cue.FloatKind, err: cue.ErrBelow.Error(), }, { value: "-4.940656458412465441765687928682213723650e-324", float: "-4.940656458412465441765687928682213723650e-324", mant: "-4940656458412465441765687928682213723650", exp: -363, float64: 0, prec: -1, fmt: 'g', kind: cue.FloatKind, err: cue.ErrAbove.Error(), }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { n := getValue(m, tc.value) if n.Kind() != tc.kind { t.Fatal("Not a number") } var mant big.Int exp, err := n.MantExp(&mant) mstr := "" if err == nil { mstr = mant.String() } if exp != tc.exp || mstr != tc.mant { t.Errorf("mantExp: got %s %d; want %s %d", mstr, exp, tc.mant, tc.exp) } b, _ := n.AppendFloat(nil, tc.fmt, tc.prec) want := tc.float if got := string(b); got != want { t.Errorf("append: got %v; want %v", got, want) } f, err := n.Float64() checkErr(t, err, tc.err, "Float64") if f != tc.float64 { t.Errorf("Float64: got %v; want %v", f, tc.float64) } }) } } func TestString(t *testing.T) { testCases := []struct { value string str string err string }{{ value: `""`, str: ``, }, { value: `"Hello world!"`, str: `Hello world!`, }, { value: `"Hello \(#world)!" #world: "world"`, str: `Hello world!`, }, { value: `string`, err: "non-concrete value string", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { str, err := getValue(m, tc.value).String() checkFatal(t, err, tc.err, "init") if str != tc.str { t.Errorf("String: got %q; want %q", str, tc.str) } b, err := getValue(m, tc.value).Bytes() checkFatal(t, err, tc.err, "init") if got := string(b); got != tc.str { t.Errorf("Bytes: got %q; want %q", got, tc.str) } r, err := getValue(m, tc.value).Reader() checkFatal(t, err, tc.err, "init") b, _ = io.ReadAll(r) if got := string(b); got != tc.str { t.Errorf("Reader: got %q; want %q", got, tc.str) } }) } } func TestError(t *testing.T) { testCases := []struct { value string err string }{{ value: `_|_`, err: "explicit error (_|_ literal) in source", }, { value: `"Hello world!"`, }, { value: `string`, err: "", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { err := getValue(m, tc.value).Err() checkErr(t, err, tc.err, "init") }) } } func TestNull(t *testing.T) { testCases := []struct { value string err string }{{ value: `v: _|_`, err: "explicit error (_|_ literal) in source", }, { value: `v: "str"`, err: "cannot use value \"str\" (type string) as null", }, { value: `v: null`, }, { value: `v: _`, err: "non-concrete value _", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, tc.value).Lookup("v") err := v.Null() checkErr(t, err, tc.err, "init") wantBool := err == nil gotBool := v.IsNull() if wantBool != gotBool { t.Fatalf("IsNull reported %v, but Null reported: %v", gotBool, err) } }) } } func TestBool(t *testing.T) { testCases := []struct { value string bool bool err string }{{ value: `_|_`, err: "explicit error (_|_ literal) in source", }, { value: `"str"`, err: "cannot use value \"str\" (type string) as bool", }, { value: `true`, bool: true, }, { value: `false`, }, { value: `bool`, err: "non-concrete value bool", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { got, err := getValue(m, tc.value).Bool() if checkErr(t, err, tc.err, "init") { if got != tc.bool { t.Errorf("got %v; want %v", got, tc.bool) } } }) } } func TestList(t *testing.T) { testCases := []struct { value string res string err string }{{ value: `_|_`, err: "explicit error (_|_ literal) in source", }, { value: `"str"`, err: "cannot use value \"str\" (type string) as list", }, { value: `[]`, res: "[]", }, { value: `[1,2,3]`, res: "[1,2,3,]", }, { value: `[for x in #y if x > 1 { x }] #y: [1,2,3]`, res: "[2,3,]", }, { value: `[int]`, err: "cannot convert incomplete value", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { l, err := getValue(m, tc.value).List() checkFatal(t, err, tc.err, "init") buf := []byte{'['} for wantIdx := 0; l.Next(); wantIdx++ { // Ensure that we can get each index as well. if got := l.Selector().Index(); got != wantIdx { t.Errorf("Index got %v; want %v", got, wantIdx) } b, err := l.Value().MarshalJSON() checkFatal(t, err, tc.err, "list.Value") buf = append(buf, b...) buf = append(buf, ',') } buf = append(buf, ']') if got := string(buf); got != tc.res { t.Errorf("got %v; want %v", got, tc.res) } }) } } func TestFields(t *testing.T) { testCases := []struct { value string res string err string opts []cue.Option path string todoV3 bool }{{ value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`, res: "{reg:4,}", }, { value: `_|_`, err: "explicit error (_|_ literal) in source", }, { value: `"str"`, err: "cannot use value \"str\" (type string) as struct", }, { value: `{}`, res: "{}", }, { value: `{a:1,b:2,c:3}`, res: "{a:1,b:2,c:3,}", }, { value: `{a:1,"_b":2,c:3,_d:4}`, res: `{a:1,"_b":2,c:3,}`, }, { value: `{_a:"a"}`, res: "{}", }, { value: `{ for k, v in #y if v > 1 {"\(k)": v} } #y: {a:1,b:2,c:3}`, res: "{b:2,c:3,}", }, { value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`, res: "{reg:4,}", }, { value: `{a:1,b:2,c:int}`, err: "cannot convert incomplete value", }, { value: ` step1: {} step2: {prefix: 3} if step2.value > 100 { step3: {prefix: step2.value} } _hidden: 3`, res: `{step1:{},step2:{"prefix":3},}`, }, { opts: []cue.Option{cue.Final()}, value: ` step1: {} if step1.value > 100 { }`, err: "undefined field: value", }, { opts: []cue.Option{cue.Concrete(true)}, value: ` step1: {} if step1.value > 100 { }`, err: "undefined field: value", }, { value: `{a!: 1, b?: 2, c: 3}`, err: "a: field is required but not present", }, { opts: []cue.Option{cue.Hidden(true)}, value: `1, _a: 2`, res: `{_a:2,}`, }, { opts: []cue.Option{cue.Definitions(true)}, value: `1, #a: 2`, res: `{#a:2,}`, }, { opts: []cue.Option{cue.Optional(true)}, value: `1, a?: 2`, err: "cannot use value 1 (type int) as struct", }, { value: `a: x, x: y, y: b: 1`, path: "a", res: `{b:1,}`, }} for _, tc := range testCases { cuetdtest.DevOnlyMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { f := getValue(m, tc.value) obj := f.LookupPath(cue.ParsePath(tc.path)) iter, err := obj.Fields(tc.opts...) checkFatal(t, err, tc.err, "init") buf := []byte{'{'} for iter.Next() { buf = append(buf, iter.Selector().String()...) buf = append(buf, ':') b, err := iter.Value().MarshalJSON() checkFatal(t, err, tc.err, "Obj.At") buf = append(buf, b...) buf = append(buf, ',') } buf = append(buf, '}') if got := string(buf); got != tc.res { t.Errorf("got %v; want %v", got, tc.res) } iter, _ = obj.Fields(tc.opts...) for iter.Next() { want, err := iter.Value().MarshalJSON() checkFatal(t, err, tc.err, "Obj.At2") got, err := obj.LookupPath(cue.MakePath(iter.Selector())).MarshalJSON() checkFatal(t, err, tc.err, "Obj.At2") if !bytes.Equal(got, want) { t.Errorf("Lookup: got %q; want %q", got, want) } } v := obj.LookupPath(cue.MakePath(cue.Str("non-existing"))) checkErr(t, v.Err(), "not found", "non-existing") }) } } func TestAllFields(t *testing.T) { testCases := []struct { value string res string err string }{{ value: `{a:1,"_b":2,c:3,_d:4}`, res: `{a:1,"_b":2,c:3,_d:4,}`, }, { value: `{_a:"a"}`, res: `{_a:"a",}`, }, { value: `{_a:"a", b?: "b", #c: 3}`, res: `{_a:"a",b?:"b",#c:3,}`, }, { // Issue #1879 value: `{a: 1, if false { b: 2 }}`, res: `{a:1,}`, }, { value: `{a!:1,b?:2,c:3}`, res: `{a!:1,b?:2,c:3,}`, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { obj := getValue(m, tc.value) var iter *cue.Iterator // Verify that the returned iterator is a pointer. iter, err := obj.Fields(cue.All()) checkFatal(t, err, tc.err, "init") buf := []byte{'{'} for iter.Next() { buf = append(buf, iter.Selector().String()...) buf = append(buf, ':') b, err := iter.Value().MarshalJSON() checkFatal(t, err, tc.err, "Obj.At") buf = append(buf, b...) buf = append(buf, ',') } buf = append(buf, '}') if got := string(buf); got != tc.res { t.Errorf("got %v; want %v", got, tc.res) } }) } } func TestFieldType(t *testing.T) { testCases := []struct { value string want string }{{ value: `{a:1,"_b":2,c:3,_d:4,#def: 1}`, want: ` StringLabel StringLabel StringLabel HiddenLabel DefinitionLabel`, }, { value: `{a!:1,b?:2,c:3}`, want: ` StringLabel|RequiredConstraint StringLabel|OptionalConstraint StringLabel`, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { obj := getValue(m, tc.value) iter, err := obj.Fields(cue.All()) if err != nil { t.Fatal(err) } b := &strings.Builder{} for iter.Next() { fmt.Fprint(b, "\n\t\t", iter.FieldType()) } if got := b.String(); got != tc.want { t.Errorf("got:%v\nwant:%v", got, tc.want) } }) } } func TestLookup(t *testing.T) { cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() val := mustCompile(t, ctx, ` #V: { x: int } #X: { [string]: int64 } & #V v: #X a: { b!: 1 c: 2 } pkg: x, x: y: "hello"`) // expr, err := parser.ParseExpr("lookup.cue", `v`, parser.DeclarationErrors, parser.AllErrors) // if err != nil { // log.Fatalf("parseExpr: %v", err) // } // v := inst.Eval(expr) type testCase struct { ref []string result string syntax string } testCases := []testCase{{ ref: []string{"a"}, result: `{ b!: 1 c: 2 }`, syntax: "{b!: 1, c: 2}", }, { // Allow descending into structs even if it has a required field error. ref: []string{"a", "c"}, result: "2", syntax: "2", }, { ref: []string{"a", "b"}, result: "_|_ // a.b: field is required but not present", syntax: "1", }, { ref: []string{"v", "x"}, result: "int64", syntax: "int64", }, { // Issue 3577 ref: []string{"pkg", "y"}, result: `"hello"`, syntax: `"hello"`, }} for _, tc := range testCases { t.Run("", func(t *testing.T) { v := val.Lookup(tc.ref...) if got := fmt.Sprintf("%+v", v); got != tc.result { t.Errorf("got %v; want %v", got, tc.result) } got := fmt.Sprint(astinternal.DebugStr(v.Eval().Syntax())) if got != tc.syntax { t.Errorf("got %v; want %v", got, tc.syntax) } v = val.Lookup() for _, ref := range tc.ref { s, err := v.Struct() if err != nil { t.Fatal(err) } fi, err := s.FieldByName(ref, false) if err != nil { t.Fatal(err) } v = fi.Value // Struct gets all fields. Skip tests with optional fields, // as the result will differ. if cue.ValueVertex(v).ArcType != adt.ArcMember { return } } if got := fmt.Sprintf("%+v", v); got != tc.result { t.Errorf("got %v; want %v", got, tc.result) } got = fmt.Sprint(astinternal.DebugStr(v.Eval().Syntax())) if got != tc.syntax { t.Errorf("got %v; want %v", got, tc.syntax) } }) } }) } func goValue(v cue.Value) interface{} { var x interface{} err := v.Decode(&x) if err != nil { return err } return x } // TODO: Exporting of Vertex as Conjunct func TestFill(t *testing.T) { // TODO: run with matrix. ctx := cuecontext.New() val := ctx.BuildExpr(ast.NewStruct("bar", ast.NewString("baz"))) if err := val.Err(); err != nil { t.Fatal(err) } testCases := []struct { in string x interface{} path string // comma-separated path out string }{{ in: ` foo: int bar: foo `, x: 3, path: "foo", out: ` foo: 3 bar: 3 `, }, { in: ` string `, x: "foo", path: "", out: ` "foo" `, }, { in: ` foo: _ `, x: val, path: "foo", out: ` {foo: {bar: "baz"}} `, }} for _, tc := range testCases { var path []string if tc.path != "" { path = strings.Split(tc.path, ",") } v := mustCompile(t, ctx, tc.in) v = v.Fill(tc.x, path...) w := mustCompile(t, ctx, tc.out) if diff := cmp.Diff(goValue(v), goValue(w)); diff != "" { t.Error(diff) t.Errorf("\ngot: %s\nwant: %s", v, w) } } } func TestFill2(t *testing.T) { // TODO: run with matrix. ctx := cuecontext.New() root := mustCompile(t, ctx, ` #Provider: { ID: string notConcrete: bool a: int b: int } `) spec := root.LookupDef("#Provider") providerInstance := spec.Fill("12345", "ID") root = root.Fill(providerInstance, "providers", "myprovider") got := fmt.Sprintf("%#v", root) want := `#Provider: { ID: string notConcrete: bool a: int b: int } providers: { myprovider: { ID: "12345" notConcrete: bool a: int b: int } }` if got != want { t.Errorf("got: %s\nwant: %s", got, want) } } func TestFillPath(t *testing.T) { cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() val := ctx.BuildExpr(ast.NewStruct("bar", ast.NewString("baz"))) if err := val.Err(); err != nil { t.Fatal(err) } testCases := []struct { in string x interface{} path cue.Path out string }{{ in: ` foo: int bar: foo `, x: 3, path: cue.ParsePath("foo"), out: ` foo: 3 bar: 3 `, }, { in: ` X="#foo": int bar: X `, x: 3, path: cue.ParsePath(`"#foo"`), out: ` "#foo": 3 bar: 3 `, }, { in: ` X="#foo": foo: int bar: X.foo `, x: 3, path: cue.ParsePath(`"#foo".foo`), out: ` "#foo": foo: 3 bar: 3 `, }, { in: ` foo: #foo: int bar: foo.#foo `, x: 3, path: cue.ParsePath("foo.#foo"), out: ` foo: { #foo: 3 } bar: 3 `, }, { in: ` foo: _foo: int bar: foo._foo `, x: 3, path: cue.MakePath(cue.Str("foo"), cue.Hid("_foo", "_")), out: ` foo: { _foo: 3 } bar: 3 `, }, { in: ` string `, x: "foo", path: cue.ParsePath(""), out: ` "foo" `, }, { in: ` foo: _ `, x: val, path: cue.ParsePath("foo"), out: ` {foo: {bar: "baz"}} `, }, { // Resolve to enclosing in: ` foo: _ x: 1 `, x: ast.NewIdent("x"), path: cue.ParsePath("foo"), out: ` {foo: 1, x: 1} `, }, { in: ` foo: { bar: _ x: 1 } `, x: ast.NewIdent("x"), path: cue.ParsePath("foo.bar"), out: ` {foo: {bar: 1, x: 1}} `, }, { // Resolve one scope up in: ` x: 1 foo: { bar: _ } `, x: ast.NewIdent("x"), path: cue.ParsePath("foo.bar"), out: ` {foo: {bar: 1}, x: 1} `, }, { // Resolve within ast expression in: ` foo: { bar: _ } `, x: ast.NewStruct( ast.NewIdent("x"), ast.NewString("1"), ast.NewIdent("y"), ast.NewIdent("x"), ), path: cue.ParsePath("foo.bar"), out: ` {foo: {bar: {x: "1", y: "1"}}} `, }, { // Resolve in non-existing in: ` foo: x: 1 `, x: ast.NewIdent("x"), path: cue.ParsePath("foo.bar.baz"), out: ` {foo: {x: 1, bar: baz: 1}} `, }, { // empty path in: ` _ #foo: 1 `, x: ast.NewIdent("#foo"), out: `{1, #foo: 1}`, }, { in: `[...int]`, x: 1, path: cue.ParsePath("0"), out: `[1]`, }, { in: `[1, ...int]`, x: 1, path: cue.ParsePath("1"), out: `[1, 1]`, }, { in: `a: {b: v: int, c: v: int}`, x: 1, path: cue.MakePath(cue.Str("a"), cue.AnyString, cue.Str("v")), out: `{ a: { b: { v: 1 } c: { v: 1 } } }`, }, { in: `a: [_]`, x: 1, path: cue.MakePath(cue.Str("a"), cue.AnyIndex, cue.Str("b")), out: `{ a: [{ b: 1 }] }`, }, { in: `a: 1`, x: 1, path: cue.MakePath(cue.Str("b").Optional()), out: `{a: 1}`, }, { in: `b: int`, x: 1, path: cue.MakePath(cue.Str("b").Optional()), out: `{b: 1}`, }} for _, tc := range testCases { t.Run("", func(t *testing.T) { v := mustCompile(t, ctx, tc.in) v = v.FillPath(tc.path, tc.x) w := mustCompile(t, ctx, tc.out) if diff := cmp.Diff(goValue(v), goValue(w)); diff != "" { t.Error(diff) t.Error(cmp.Diff(goValue(v), goValue(w))) t.Errorf("\ngot: %s\nwant: %s", v, w) } }) } }) } func TestFillPathError(t *testing.T) { testCases := []struct { in string x interface{} path cue.Path err string }{{ // unsupported type. in: `_`, x: make(chan int), err: "unsupported Go type (chan int)", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() v := mustCompile(t, ctx, tc.in) v = v.FillPath(tc.path, tc.x) err := v.Err() if err == nil { t.Errorf("unexpected success") } else if got := err.Error(); !strings.Contains(got, tc.err) { t.Errorf("\ngot: %s\nwant: %s", got, tc.err) } }) } } func TestAllows(t *testing.T) { testCases := []struct { desc string in string sel cue.Selector allow bool todo_nosharing bool }{{ desc: "allow new field in open struct", in: ` x: { a: int } `, sel: cue.Str("b"), allow: true, }, { desc: "disallow new field in definition", in: ` x: #Def #Def: { a: int } `, sel: cue.Str("b"), }, { desc: "disallow new field in explicitly closed struct", in: ` x: close({ a: int }) `, sel: cue.Str("b"), }, { desc: "allow field in pattern", in: ` x: #X #X: [>"a"]: 1 `, sel: cue.Str("b"), allow: true, }, { desc: "allow index in open list", in: ` x: [...int] `, sel: cue.Index(100), allow: true, }, { desc: "disallow index in closed list", in: ` x: [] `, sel: cue.Index(0), }, { desc: "allow existing index in closed list", in: ` x: [1] `, sel: cue.Index(0), allow: true, }, { desc: "definition in non-def closed list", in: ` x: [1] `, sel: cue.Def("#foo"), allow: true, }, { // TODO(disallow) desc: "definition in def open list", in: ` x: #Def x: [1] #Def: [...int] `, sel: cue.Def("#foo"), allow: true, }, { desc: "field in def open list", in: ` x: #Def x: [1] #Def: [...int] `, sel: cue.Str("foo"), }, { desc: "definition in open scalar", in: ` x: 1 `, sel: cue.Def("#foo"), allow: true, }, { desc: "field in scalar", in: ` x: #Def x: 1 #Def: int `, sel: cue.Str("foo"), }, { desc: "any index in closed list", in: ` x: [1] `, sel: cue.AnyIndex, }, { desc: "any index in open list", in: ` x: [...int] `, sel: cue.AnyIndex, allow: true, }, { desc: "definition in open scalar", in: ` x: 1 `, sel: cue.AnyDefinition, allow: true, }, { desc: "field in open scalar", in: ` x: 1 `, sel: cue.AnyString, }, { // TODO: note that this may be affected by https://cuelang.org/issue/543 // if or when we decide to implement it in the future. desc: "definition in closed scalar", in: ` x: #Def x: 1 #Def: int `, sel: cue.AnyDefinition, allow: true, }, { desc: "allow field in any", in: ` x: _ `, sel: cue.AnyString, allow: true, }, { desc: "allow index in any", in: ` x: _ `, sel: cue.AnyIndex, allow: true, }, { desc: "allow index in disjunction", in: ` x: [...int] | 1 `, sel: cue.AnyIndex, allow: true, }, { desc: "allow index in disjunction", in: ` x: [] | [...int] `, sel: cue.AnyIndex, allow: true, }, { desc: "disallow index in disjunction", in: ` x: [1, 2] | [3, 2] `, sel: cue.AnyIndex, }, { desc: "disallow index in non-list disjunction", in: ` x: "foo" | 1 `, sel: cue.AnyIndex, }, { desc: "allow label in disjunction", in: ` x: {} | 1 `, sel: cue.AnyString, allow: true, }, { desc: "allow label in disjunction", in: ` x: #Def #Def: { a: 1 } | { b: 1, ... } `, sel: cue.AnyString, allow: true, todo_nosharing: true, }, { desc: "disallow label in disjunction", in: ` x: #Def #Def: { a: 1 } | { b: 1 } `, sel: cue.AnyString, }, { desc: "pattern constraint", in: ` x: #PC #PC: [>"m"]: int `, sel: cue.Str(""), }, { desc: "pattern constraint", in: ` x: #PC #PC: [>"m"]: int `, sel: cue.Str("z"), allow: true, }, { desc: "any in pattern constraint", in: ` x: #PC #PC: [>"m"]: int `, sel: cue.AnyString, }, { desc: "any in pattern constraint", in: ` x: #PC #PC: [>" "]: int `, sel: cue.AnyString, }} path := cue.ParsePath("x") for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.desc, func(t *testing.T, m *cuetdtest.M) { if tc.todo_nosharing { m.TODO_NoSharing(t) } ctx := m.CueContext() v := mustCompile(t, ctx, tc.in) v = v.LookupPath(path) got := v.Allows(tc.sel) if got != tc.allow { t.Errorf("got %v; want %v", got, tc.allow) } }) } } func TestFillFloat(t *testing.T) { // This tests panics for issue #749 want := `{ x: 3.14 }` filltest := func(x interface{}) { ctx := cuecontext.New() val := mustCompile(t, ctx, ` x: number `) val = val.Fill(x, "x") got := fmt.Sprint(val) if got != want { t.Errorf("got: %s\nwant: %s", got, want) } } filltest(float32(3.14)) filltest(float64(3.14)) filltest(big.NewFloat(3.14)) } func TestValue_LookupDef(t *testing.T) { testCases := []struct { in string def string // comma-separated path exists bool out string }{{ in: `#foo: 3`, def: "#foo", out: `3`, }, { in: `_foo: 3`, def: "_foo", out: `_|_ // field not found: #_foo`, }, { in: `_#foo: 3`, def: "_#foo", out: `_|_ // field not found: _#foo`, }, { in: `"foo", #foo: 3`, def: "#foo", out: `3`, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.def, func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() v := mustCompile(t, ctx, tc.in) v = v.LookupDef(tc.def) got := fmt.Sprint(v) if got != tc.out { t.Errorf("\ngot: %s\nwant: %s", got, tc.out) } }) } } // TODO: trim down to individual defaults? func TestDefaults(t *testing.T) { testCases := []struct { value string def string val string ok bool }{{ value: `number | *1`, def: "1", val: "number", ok: true, }, { value: `1 | 2 | *3`, def: "3", val: "1|2|3", ok: true, }, { value: `*{a:1,b:2}|{a:1}|{b:2}`, def: "{a:1,b:2}", val: "{a: 1}|{b: 2}", ok: true, }, { value: `{a:1}&{b:2}`, def: `{a:1,b:2}`, val: ``, ok: false, }, { value: `*_|_ | (*"x" | string)`, def: `"x" | string`, val: `"x"|string`, ok: false, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, "a: "+tc.value).Lookup("a") v = v.Eval() d, ok := v.Default() if ok != tc.ok { t.Errorf("hasDefault: got %v; want %v", ok, tc.ok) } if got := compactRawStr(d); got != tc.def { t.Errorf("default: got %v; want %v", got, tc.def) } op, val := d.Expr() if op != cue.OrOp { return } vars := []string{} for _, v := range val { vars = append(vars, fmt.Sprint(v)) } if got := strings.Join(vars, "|"); got != tc.val { t.Errorf("value: got %v; want %v", got, tc.val) } }) } } func TestLen(t *testing.T) { testCases := []struct { input string length string }{{ input: "[1, 3]", length: "2", }, { input: "[1, 3, ...]", length: "int & >=2", }, { input: `"foo"`, length: "3", }, { input: `'foo'`, length: "3", // TODO: Currently not supported. // }, { // input: "{a:1, b:3, a:1, c?: 3, _hidden: 4}", // length: "2", }, { input: "3", length: "_|_ // len not supported for type int", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.input, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, "a: "+tc.input).Lookup("a") length := v.Len() if got := fmt.Sprint(length); got != tc.length { t.Errorf("length: got %v; want %v", got, tc.length) } }) } } func TestTemplate(t *testing.T) { testCases := []struct { value string path []string want string skip bool }{{ value: ` a: [Name=string]: Name `, path: []string{"a", ""}, want: `"label"`, }, { value: ` [Name=string]: { a: Name } `, path: []string{"", "a"}, want: `"label"`, }, { value: ` [Name=string]: { a: Name } `, path: []string{""}, want: `{"a":"label"}`, }, { value: ` a: [Foo=string]: [Bar=string]: { b: Foo+Bar } `, path: []string{"a", "", ""}, want: `{"b":"labellabel"}`, }, { value: ` a: [Foo=string]: b: [Bar=string]: { c: Foo+Bar } a: foo: b: [Bar=string]: { d: Bar } `, path: []string{"a", "foo", "b", ""}, want: `{"c":"foolabel","d":"label"}`, skip: true, // TODO: reordering }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { if tc.skip { m.TODO_V3(t) // P2: reordering } v := getValue(m, tc.value) for _, p := range tc.path { if p == "" { v = v.Template()("label") } else { v = v.Lookup(p) } } b, err := v.MarshalJSON() if err != nil { t.Fatal(err) } if got := string(b); got != tc.want { t.Errorf("\n got: %q\nwant: %q", got, tc.want) } }) } } func TestElem(t *testing.T) { testCases := []struct { value string path []string want string skip bool }{{ value: ` a: [...int] `, path: []string{"a", ""}, want: `int`, }, { value: ` [Name=string]: { a: Name } `, path: []string{"", "a"}, want: `string`, }, { value: ` [Name=string]: { a: Name } `, path: []string{""}, want: "{\n\ta: string\n}", }, { value: ` a: [Foo=string]: [Bar=string]: { b: Foo+Bar } `, path: []string{"a", "", ""}, want: "{\n\tb: string + string\n}", }, { value: ` a: [Foo=string]: b: [Bar=string]: { c: Foo+Bar } a: foo: b: [Bar=string]: { d: Bar } `, path: []string{"a", "foo", "b", ""}, want: "{\n\tc: \"foo\" + string\n\td: string\n}", skip: true, // TODO(p3): Skip because this is just a reordering. }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { if tc.skip { m.TODO_V3(t) // P2: reordering } v := getValue(m, tc.value) cue.ValueVertex(v).Finalize(cue.ValueCtx(v)) for _, p := range tc.path { if p == "" { var ok bool v, ok = v.Elem() if !ok { t.Fatal("expected element") } } else { v = v.Lookup(p) } } got := fmt.Sprint(v) if got != tc.want { t.Errorf("\n got: %q\nwant: %q", got, tc.want) } }) } } func TestSubsume(t *testing.T) { a := cue.ParsePath("a") b := cue.ParsePath("b") testCases := []struct { value string pathA cue.Path pathB cue.Path options []cue.Option want bool }{{ value: `4`, want: true, }, { value: `a: string, b: "foo"`, pathA: a, pathB: b, want: true, }, { value: `a: string, b: "foo"`, pathA: b, pathB: a, want: false, }, { value: `a: {a: string, b: 4}, b: {a: "foo", b: 4}`, pathA: a, pathB: b, want: true, }, { value: `a: [string, 4], b: ["foo", 4]`, pathA: a, pathB: b, want: true, }, { value: `a: [...string], b: ["foo"]`, pathA: a, pathB: b, want: true, }, { value: `a: [...int], b: ["foo"]`, pathA: a, pathB: b, want: false, }, { // Issue #566 // Closed struct subsuming open struct. value: ` #Run: { action: "run", command: [...string] } b: { action: "run", command: ["echo", "hello"] } `, pathA: cue.ParsePath("#Run"), pathB: b, // NOTE: this is for v0.2 compatibility. Logically a closed struct // does not subsume an open struct. One could argue that the default // of an open struct is the closed struct with the minimal number // of fields that is an instance of it, though. want: true, // open struct is not subsumed by closed if not final. }, { // Issue #566 // Closed struct subsuming open struct. value: ` #Run: { action: "run", command: [...string] } b: { action: "run", command: ["echo", "hello"] } `, pathA: cue.ParsePath("#Run"), pathB: b, options: []cue.Option{cue.Final()}, want: true, }, { // default value: ` a: <5 b: *3 | int `, pathA: a, pathB: b, want: true, }, { // Disable default elimination. value: ` a: <5 b: *3 | int `, pathA: a, pathB: b, options: []cue.Option{cue.Raw()}, want: false, }, { value: ` #A: { exact: string } | { regex: string } #B: { exact: string } | { regex: string } `, pathA: cue.ParsePath("#A"), pathB: cue.ParsePath("#B"), options: []cue.Option{}, want: true, }, { value: ` import "time" a: time.Format(time.ANSIC) b: 1 `, pathA: a, pathB: b, want: false, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.value, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, tc.value) a := v.LookupPath(tc.pathA) b := v.LookupPath(tc.pathB) got := a.Subsume(b, tc.options...) == nil if got != tc.want { t.Errorf("got %v (%v); want %v (%v)", got, a, tc.want, b) } }) } } func TestUnify(t *testing.T) { a := "a" b := "b" type testCase struct { value string pathA string pathB string want string } testCases := []testCase{{ value: `4`, want: `4`, }, { value: `a: string, b: "foo"`, pathA: a, pathB: b, want: `"foo"`, }, { value: `a: string, b: "foo"`, pathA: b, pathB: a, want: `"foo"`, }, { value: `a: {a: string, b: 4}, b: {a: "foo", b: 4}`, pathA: a, pathB: b, want: `{"a":"foo","b":4}`, }, { value: `a: [string, 4], b: ["foo", 4]`, pathA: a, pathB: b, want: `["foo",4]`, }, { value: `a: {a: string, _hidden: int, _#hidden: int}, b: close({a: "foo"})`, pathA: a, pathB: b, want: `{"a":"foo"}`, }, { // Issue #2325: let should not result in a closedness error. value: `#T: { ... } b: { let foobar = {} _fb: foobar }`, pathA: "#T", pathB: b, want: `{}`, }, { value: ` a: #A: "foo" #B: {...} `, pathA: a, pathB: "#B", want: `{}`, }} // TODO(tdtest): use cuetest.Run when supported. cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { tdtest.Run(t, testCases, func(t *cuetest.T, tc *testCase) { v := getValue(m, tc.value) x := v.LookupPath(cue.ParsePath(tc.pathA)) y := v.LookupPath(cue.ParsePath(tc.pathB)) b, err := x.Unify(y).MarshalJSON() if err != nil { t.Fatal(err) } t.Equal(string(b), tc.want) }) }) } // TestUnify2 is similar to TestUnify, but uses CompileString and Validate. func TestUnify2(t *testing.T) { type testCase struct { a string b string err bool } testCases := []testCase{{ a: `null | close({})`, b: `quux: "boom"`, err: true, }, { a: `close({[=~"a"]: _})`, b: `a: 1`, }, { a: `close({{[=~"a"]: _}})`, b: `a: 1`, }} adt.DebugDeps = true cuetdtest.Run(t, testCases, func(t *cuetdtest.T, tc *testCase) { ctx := t.M.CueContext() a := ctx.CompileString(tc.a) b := ctx.CompileString(tc.b) // r := (*runtime.Runtime)(ctx) // r.SetDebugOptions(&cuedebug.Config{LogEval: 1}) c := a.Unify(b) err := c.Validate() t.Equal(err != nil, tc.err, "hasError") t.Log("error:", err) }) } func TestUnifyAccept(t *testing.T) { type testCase struct { value string want string } testCases := []testCase{{ value: `#v: 4, #w: 4, #accept: int`, want: `4`, }, { value: `#v: string, #w: "foo", #accept: string`, want: `"foo"`, }, { value: `#v: {a: "foo"}, #w: {b: 4}, #accept: {a: string, b: int}`, want: `{"a":"foo","b":4}`, }, { value: `#v: [string, 4], #w: ["foo", 4], #accept: [string, int, ...]`, want: `["foo",4]`, }, { value: `#v: {a: string, b: 1, _#hidden: int}, #w: {a: "foo"}, #accept: {...}`, want: `{"a":"foo","b":1}`, }, { // Issue #2325: let should not result in a closedness error. value: `#accept: { ... } #v: {} #w: { let foobar = {} _fb: foobar }`, want: `{}`, }, { value: ` #v: #v: "foo" #w: {b:1} #accept: {...} `, want: `{"b":1}`, }} // TODO(tdtest): use cuetest.Run when supported. cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { tdtest.Run(t, testCases, func(t *cuetest.T, tc *testCase) { v := getValue(m, tc.value) x := v.LookupPath(cue.ParsePath("#v")) y := v.LookupPath(cue.ParsePath("#w")) a := v.LookupPath(cue.ParsePath("#accept")) b, err := x.UnifyAccept(y, a).MarshalJSON() if err != nil { t.Fatal(err) } t.Equal(string(b), tc.want) }) }) } func TestEquals(t *testing.T) { testCases := []struct { a, b string want bool }{{ `4`, `4`, true, }, { `"str"`, `2`, false, }, { `2`, `3`, false, }, { `[1]`, `[3]`, false, }, { `[{a: 1,...}]`, `[{a: 1,...}]`, true, }, { `[]`, `[]`, true, }, { `{ a: b, b: a, }`, `{ a: b, b: a, }`, true, }, { `{ a: "foo", b: "bar", }`, `{ a: "foo", }`, false, }, { // Ignore closedness `{ #Foo: { k: 1 }, a: #Foo }`, `{ #Foo: { k: 1 }, a: { k: 1 } }`, true, }, { // Ignore optional fields `{ #Foo: { k: 1 }, a: #Foo }`, `{ #Foo: { k: 1 }, a: { #Foo, i?: 1 } }`, true, }, { // Treat embedding as equal `{ a: 2, b: { 3 } }`, `{ a: { 2 }, b: 3 }`, true, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() a := mustCompile(t, ctx, tc.a) b := mustCompile(t, ctx, tc.b) got := a.Equals(b) if got != tc.want { t.Errorf("got %v; want %v", got, tc.want) } }) } } // TODO: options: disallow cycles. func TestValidate(t *testing.T) { testCases := []struct { desc string in string err bool opts []cue.Option skip bool }{{ desc: "issue #51", in: ` a: [string]: foo a: b: {} `, err: true, }, { desc: "concrete", in: ` a: 1 b: { c: 2, d: 3 } c: d: e: f: 5 g?: int `, opts: []cue.Option{cue.Concrete(true)}, }, { desc: "definition error", in: ` #b: 1 & 2 `, opts: []cue.Option{}, err: true, }, { desc: "definition error okay if optional", in: ` #b?: 1 & 2 `, opts: []cue.Option{}, }, { desc: "definition with optional", in: ` #b: { a: int b?: >=0 } `, opts: []cue.Option{cue.Concrete(true)}, }, { desc: "disjunction", in: `a: 1 | 2`, }, { desc: "disjunction concrete", in: `a: 1 | 2`, opts: []cue.Option{cue.Concrete(true)}, err: true, }, { desc: "incomplete concrete", in: `a: string`, }, { desc: "incomplete", in: `a: string`, opts: []cue.Option{cue.Concrete(true)}, err: true, }, { desc: "list", in: `a: [{b: string}, 3]`, }, { desc: "list concrete", in: `a: [{b: string}, 3]`, opts: []cue.Option{cue.Concrete(true)}, err: true, }, { desc: "allow cycles", in: ` a: b - 100 b: a + 100 c: [c[1], c[0]] `, }, { desc: "disallow cycles", in: ` a: b - 100 b: a + 100 c: [c[1], c[0]] `, opts: []cue.Option{cue.DisallowCycles(true)}, err: true, // TODO: in the new evaluator these are not considered to be cycles // but rather incomplete errors. This is actually the correct behavior // and the old evaluator treats errors like this by default. // The option tested in this test was added for backwards compatibility // when the old evaluator was made to treat these kinds of errors // equally. With the new evaluator we can no longer distinguish these // errors. For now, at least. Consider what to do with this option. skip: true, }, { desc: "builtins are okay", in: ` import "time" a: { b: time.Duration } | { c: time.Duration } `, }, { desc: "comprehension error", in: ` a: { if b == "foo" { field: 2 } } `, err: true, }, { desc: "ignore optional in schema", in: ` #Schema1: { a?: int } instance1: #Schema1 `, opts: []cue.Option{cue.Concrete(true)}, }, { desc: "issue324", in: ` import "encoding/yaml" x: string a: b: c: *["\(x)"] | _ d: yaml.Marshal(a.b) `, }, { desc: "allow non-concrete values for definitions", in: ` variables: #variables {[!~"^[.]"]: #job} #variables: [string]: int | string #job: ({a: int} | {b: int}) & { "variables"?: #variables } `, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.desc, func(t *testing.T, m *cuetdtest.M) { if tc.skip { m.TODO_V3(t) // P1: wrong results } ctx := m.CueContext() val := ctx.CompileString(tc.in, cue.Filename("validate")) err := val.Validate(tc.opts...) if gotErr := err != nil; gotErr != tc.err { t.Errorf("got %v; want %v", err, tc.err) } }) } } func TestPath(t *testing.T) { config := ` a: b: c: 5 b: { b1: 3 b2: 4 "b 3": 5 "4b": 6 l: [ {a: 2}, {c: 2}, ] } ` mkpath := func(p ...string) []string { return p } testCases := [][]string{ mkpath("a", "b", "c"), mkpath("b", "l", "1", "c"), mkpath("b", `"b 3"`), mkpath("b", `"4b"`), } for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, strings.Join(tc, "."), func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() val := mustCompile(t, ctx, config) v := val.Lookup(tc[0]) for _, e := range tc[1:] { if '0' <= e[0] && e[0] <= '9' { i, err := strconv.Atoi(e) if err != nil { t.Fatal(err) } iter, err := v.List() if err != nil { t.Fatal(err) } for c := 0; iter.Next(); c++ { if c == i { v = iter.Value() break } } } else if e[0] == '"' { v = v.Lookup(e[1 : len(e)-1]) } else { v = v.Lookup(e) } } got := cue.PathToStrings(v.Path()) if !reflect.DeepEqual(got, tc) { t.Errorf("got %v; want %v", got, tc) } }) } } func TestValueLookup(t *testing.T) { config := ` a: { a: 0 b: 1 c: 2 } b: { d: a.a e: int } ` strList := func(s ...string) []string { return s } testCases := []struct { config string path []string str string notExists bool }{{ config: "_|_", path: strList(""), str: "explicit error (_|_ literal) in source", }, { config: "_|_", path: strList("a"), str: "explicit error (_|_ literal) in source", }, { config: config, path: strList(), str: "{a:{a:0,b:1,c:2},b:{d:0,e:int}", }, { config: config, path: strList("a", "a"), str: "0", }, { config: config, path: strList("a"), str: "{a:0,b:1,c:2}", }, { config: config, path: strList("b", "d"), str: "0", }, { config: config, path: strList("c", "non-existing"), str: "not found", notExists: true, }, { config: config, path: strList("b", "d", "lookup in non-struct"), str: "cannot use value 0 (type int) as struct", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.str, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, tc.config).Lookup(tc.path...) if got := !v.Exists(); got != tc.notExists { t.Errorf("exists: got %v; want %v", got, tc.notExists) } got := cue.ValueCtx(v).Str(cue.ValueVertex(v)) if tc.str == "" { t.Fatalf("str empty, got %q", got) } if !strings.Contains(got, tc.str) { t.Errorf("\n got %v\nwant %v", got, tc.str) } }) } } func cmpError(a, b error) bool { if a == nil { return b == nil } if b == nil { return a == nil } return a.Error() == b.Error() } // TODO: duplicate docs. func TestValueDoc(t *testing.T) { const config = ` // foobar defines at least foo. package foobar // A Foo fooses stuff. Foo: { // field1 is an int. field1: int field2: int // duplicate field comment dup3: int } // foos are instances of Foo. foos: [string]: Foo // My first little foo. foos: MyFoo: { // local field comment. field1: 0 // Dangling comment. // other field comment. field2: 1 // duplicate field comment dup3: int } bar: { // comment from bar on field 1 field1: int // comment from bar on field 2 field2: int // don't include this } baz: bar & { // comment from baz on field 1 field1: int field2: int } ` config2 := ` // Another Foo. Foo: {} ` cuetdtest.FullMatrix.Do(t, func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() v1 := mustCompile(t, ctx, config) v2 := mustCompile(t, ctx, config2) both := v1.Unify(v2) testCases := []struct { val cue.Value path string doc string skip bool }{{ val: v1, path: "foos", doc: "foos are instances of Foo.\n", }, { val: v1, path: "foos MyFoo", doc: "My first little foo.\n", }, { val: v1, path: "foos MyFoo field1", doc: `local field comment. field1 is an int. `, }, { val: v1, path: "foos MyFoo field2", doc: "other field comment.\n", }, { // Duplicates are now removed. val: v1, path: "foos MyFoo dup3", doc: "duplicate field comment\n", }, { val: v1, path: "bar field1", doc: "comment from bar on field 1\n", }, { val: v1, path: "baz field1", doc: `comment from bar on field 1 comment from baz on field 1 `, // New evaluaotor orders the comments differently (arguably better). skip: true, }, { val: v1, path: "baz field2", doc: "comment from bar on field 2\n", }, { val: v2, path: "Foo", doc: `Another Foo. `, }, { val: both, path: "Foo", doc: `A Foo fooses stuff. Another Foo. `, }} for _, tc := range testCases { if tc.skip { m.TODO_V3(t) // P2: reordering } t.Run("field:"+tc.path, func(t *testing.T) { v := tc.val.Lookup(strings.Split(tc.path, " ")...) doc := docStr(v.Doc()) if doc != tc.doc { t.Errorf("doc: got:\n%vwant:\n%v", doc, tc.doc) } }) } want := "foobar defines at least foo.\n" if got := docStr(v1.Doc()); got != want { t.Errorf("pkg: got:\n%vwant:\n%v", got, want) } }) } func docStr(docs []*ast.CommentGroup) string { doc := "" for _, d := range docs { if doc != "" { doc += "\n" } doc += d.Text() } return doc } // TODO: unwrap marshal error // TODO: improve error messages func TestMarshalJSON(t *testing.T) { type testCase struct { value string json string err string } testCases := []testCase{{ value: `""`, json: `""`, }, { value: `null`, json: `null`, }, { value: `_|_`, err: "explicit error (_|_ literal) in source", }, { value: `(a.b) a: {}`, err: "undefined field", }, { value: `true`, json: `true`, }, { value: `false`, json: `false`, }, { value: `bool`, err: "cannot convert incomplete value", }, { value: `"str"`, json: `"str"`, }, { value: `12_000`, json: `12000`, }, { value: `12.000`, json: `12.000`, }, { value: `12M`, json: `12000000`, }, { value: `3.0e100`, json: `3.0E+100`, }, { value: `0/0`, err: "division undefined", }, { value: `[]`, json: `[]`, }, { value: `[1, 2, 3]`, json: `[1,2,3]`, }, { value: `[int]`, err: `0: cannot convert incomplete value`, }, { value: `{}`, json: `{}`, }, { value: `{a: 2, b: 3, c: ["A", "B"]}`, json: `{"a":2,"b":3,"c":["A","B"]}`, }, { value: `{a: 2, b: 3, c: [string, "B"]}`, err: `c.0: cannot convert incomplete value`, }, { value: `{a: [{b: [0, {c: string}] }] }`, err: `a.0.b.1.c: cannot convert incomplete value`, }, { value: `{foo?: 1, bar?: 2, baz: 3}`, json: `{"baz":3}`, }, { value: `{foo!: 1, bar: 2}`, err: "cue: marshal error: foo: field is required but not present", }, { // Has an unresolved cycle, but should not matter as all fields involved // are optional value: `{foo?: bar, bar?: foo, baz: 3}`, json: `{"baz":3}`, }, { // Issue #107 value: `a: 1.0/1`, json: `{"a":1.0}`, }, { // Issue #108 value: ` a: int a: >0 a: <2 b: int b: >=0.9 b: <1.1 c: int c: >1 c: <=2 d: int d: >=1 d: <=1.5 e: int e: >=1 e: <=1.32 f: >=1.1 & <=1.1 `, json: `{"a":1,"b":1,"c":2,"d":1,"e":1,"f":1.1}`, }, { value: ` #Task: { { op: "pull" tag: *"latest" | string tagInString: tag + "dd" } | { op: "scratch" } } foo: #Task & {"op": "pull"} `, json: `{"foo":{"op":"pull","tag":"latest","tagInString":"latestdd"}}`, }, { // Issue #326 value: `x: "\(string)": "v"`, err: `x: invalid interpolation`, }, { // Issue #326 value: `x: "\(bool)": "v"`, err: `invalid interpolation`, }, { // Issue #326 value: ` x: { for k, v in y { "\(k)": v } } y: {} `, json: `{"x":{},"y":{}}`, }, { // Issue #326 value: ` x: { for k, v in y { "\(k)": v } } y: _ `, err: `x: cannot range over y (incomplete type _)`, }, { value: ` package foo #SomeBaseType: { "a" | "b" #AUTO: "z" } V1: ("x" | "y") | *"z" V2: ("x" | "y") | *#SomeBaseType.#AUTO `, err: "cue: marshal error: V2: cannot convert incomplete value \"|((string){ \\\"x\\\" }, (string){ \\\"y\\\" })\" to JSON", }} for i, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%d/%v", i, tc.value), func(t *testing.T, m *cuetdtest.M) { m.TODO_V3(t) // P1: wrong output val := getValue(m, tc.value) b, err := val.MarshalJSON() checkFatal(t, err, tc.err, "init") if got := string(b); got != tc.json { t.Errorf("\n got %v;\nwant %v", got, tc.json) } }) } } func TestWalk(t *testing.T) { testCases := []struct { value string out string }{{ value: `""`, out: `""`, }, { value: `null`, out: `null`, }, { value: `_|_`, out: "_|_(explicit error (_|_ literal) in source)", }, { value: `(a.b) a: {}`, out: `_|_(undefined field: b)`, }, { value: `true`, out: `true`, }, { value: `false`, out: `false`, }, { value: `bool`, out: "bool", }, { value: `"str"`, out: `"str"`, }, { value: `12_000`, out: `12000`, // out: `12_000`, }, { value: `12.000`, out: `12.000`, }, { value: `12M`, out: `12000000`, // out: `12M`, }, { value: `3.0e100`, out: `3.0e+100`, // out: `3.0e100`, }, { value: `[]`, out: `[]`, }, { value: `[1, 2, 3]`, out: `[1,2,3]`, }, { value: `[int]`, out: `[int]`, }, { value: `3 * [1, 2]`, out: `_|_(Multiplication of lists is superseded by list.Repeat; see https://cuelang.org/e/v0.11-list-arithmetic)`, }, { value: `[7, 8] + [1, 2]`, out: `_|_(Addition of lists is superseded by list.Concat; see https://cuelang.org/e/v0.11-list-arithmetic)`, }, { value: `{}`, out: `{}`, }, { value: `{a: 2, b: 3, c: ["A", "B"]}`, out: `{a:2,b:3,c:["A","B"]}`, }} for i, tc := range testCases { cuetdtest.FullMatrix.Run(t, fmt.Sprintf("%d/%v", i, tc.value), func(t *testing.T, m *cuetdtest.M) { m.TODO_V3(t) // P1: missing undefined field val := getValue(m, tc.value) buf := []byte{} stripComma := func() { if n := len(buf) - 1; buf[n] == ',' { buf = buf[:n] } } val.Walk(func(v cue.Value) bool { v = v.Eval() if !cue.ValueVertex(v).Label.IsInt() { if k, ok := v.Label(); ok { buf = append(buf, k+":"...) } } switch v.Kind() { case cue.StructKind: buf = append(buf, '{') case cue.ListKind: buf = append(buf, '[') default: if b := cue.ValueVertex(v).Bottom(); b != nil { s := cue.DebugStr(cue.ValueCtx(v), b) buf = append(buf, fmt.Sprint(s, ",")...) return true } buf = append(buf, fmt.Sprint(v, ",")...) } return true }, func(v cue.Value) { switch v.Kind() { case cue.StructKind: stripComma() buf = append(buf, "},"...) case cue.ListKind: stripComma() buf = append(buf, "],"...) } }) stripComma() if got := string(buf); got != tc.out { t.Errorf("\n got %v;\nwant %v", got, tc.out) } }) } } func TestReferencePath(t *testing.T) { testCases := []struct { input string want string wantImportPath string alt string }{{ input: "v: w: x: _|_", want: "", }, { input: "v: w: x: 2", want: "", }, { input: "v: w: x: a, a: 1", want: "a", }, { input: "v: w: x: a.b.c, a: b: c: 1", want: "a.b.c", }, { input: "if true { v: w: x: a, a: 1 }", want: "a", }, { input: "v: w: x: w.a.b.c, v: w: a: b: c: 1", want: "v.w.a.b.c", }, { input: `v: w: x: w.a.b.c, v: w: a: b: c: 1, #D: 3, opt?: 3, "v\(#D)": 3, X: {a: 3}, X`, want: "v.w.a.b.c", }, { input: ` v: w: x: w.a[bb]["c"] v: w: a: b: c: 1 bb: "b"`, want: "v.w.a.b.c", }, { input: ` X="\(y)": 1 v: w: x: X // TODO: Move up for crash y: "foo"`, want: "foo", }, { input: ` v: w: _ v: [X=string]: x: a[X] a: w: 1`, want: "a.w", }, { input: `v: { for t in src { w: "t\(t)": 1 w: "\(t)": w["t\(t)"] } }, src: ["x", "y"]`, want: "v.w.tx", }, { input: ` v: w: x: a a: 1 for i in [] { } `, want: "a", }, { input: ` v: w: close({x: a}) a: 1 `, want: "a", }, { input: ` import "math" v: w: x: math.Pi `, want: "Pi", wantImportPath: "math", alt: "3.14159265358979323846264338327950288419716939937510582097494459", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() val := ctx.CompileString(tc.input, cue.Filename("in")) v := val.Lookup("v", "w", "x") root, path := v.ReferencePath() if got := path.String(); got != tc.want { t.Errorf("\n got %v;\nwant %v", got, tc.want) } if tc.want != "" { want := "1" if tc.alt != "" { want = tc.alt } v := fmt.Sprint(root.LookupPath(path)) if v != want { t.Errorf("path resolved to %s; want %s", v, want) } buildInst := root.BuildInstance() if buildInst == nil { t.Fatalf("no build instance found for reference path root") } if got, want := buildInst.ImportPath, tc.wantImportPath; got != want { t.Errorf("unexpected import path; got %q want %q", got, want) } } inst, a := v.Reference() if got := strings.Join(a, "."); got != tc.want { t.Errorf("\n got %v;\nwant %v", got, tc.want) } if tc.want != "" { want := "1" if tc.alt != "" { want = tc.alt } v := fmt.Sprint(inst.Lookup(a...)) if v != want { t.Errorf("path resolved to %s; want %s", v, want) } } }) } } func TestZeroValueBuildInstance(t *testing.T) { inst := cue.Value{}.BuildInstance() if inst != nil { t.Error("unexpected non-nil instance") } } func TestPos(t *testing.T) { testCases := []struct { value string pos string skip bool }{{ value: ` a: string a: "foo"`, pos: "3:4", }, { value: ` a: x: string a: x: "x"`, pos: "2:4", // the position of the new evaluator is also correct, and actually // better. skip: true, }, { // Prefer struct conjuncts with actual fields. value: ` a: [string]: string a: x: "x"`, pos: "3:4", }, { value: ` a: [string]: [string]: string a: x: y: "x"`, pos: "3:4", }, { value: ` a: [string]: [string]: [string]: string a: x: y: z: "x"`, pos: "3:4", }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { if tc.skip { m.TODO_V3(t) // P3: different position } c := m.CueContext() v := c.CompileString(tc.value) v = v.LookupPath(cue.ParsePath("a")) pos := v.Pos().String() if pos != tc.pos { t.Errorf("got %v; want %v", pos, tc.pos) } }) } } func TestPathCorrection(t *testing.T) { testCases := []struct { input string lookup func(i cue.Value) cue.Value want string skip bool }{{ input: ` a: b: { c: d: b } `, lookup: func(i cue.Value) cue.Value { op, a := i.Lookup("a", "b", "c", "d").Expr() _ = op return a[0] // structural cycle errors. }, want: "a", }, { // TODO: embedding: have field operators. input: ` a: { {x: c} c: 3 } `, lookup: func(i cue.Value) cue.Value { op, a := i.Lookup("a").Expr() _ = op return a[0].Lookup("x") }, want: "a.c", }, { // TODO: implement proper Elem() input: ` a: b: [...T] a: b: [...T] T: int `, lookup: func(i cue.Value) cue.Value { v, _ := i.Lookup("a", "b").Elem() _, a := v.Expr() return a[0] }, want: "T", }, { input: ` #S: { b?: [...#T] b?: [...#T] } #T: int `, lookup: func(i cue.Value) cue.Value { v := i.LookupDef("#S") f, _ := v.LookupField("b") v, _ = f.Value.Elem() _, a := v.Expr() return a[0] }, want: "#T", }, { input: ` #S: { a?: [...#T] b?: [...#T] } #T: int `, lookup: func(i cue.Value) cue.Value { v := i.LookupDef("#S") f, _ := v.LookupField("a") x := f.Value f, _ = v.LookupField("b") y := f.Value u := x.Unify(y) v, _ = u.Elem() _, a := v.Expr() return a[0] }, want: "#T", }, { input: ` #a: { close({}) | close({c: #T}) | close({d: string}) #T: {b: 3} } `, lookup: func(i cue.Value) cue.Value { f, _ := i.LookupField("#a") _, a := f.Value.Expr() // & _, a = a[0].Expr() // | return a[1].Lookup("c") }, want: "#a.#T", }, { input: ` package foo #Struct: { #T: int {b?: #T} }`, want: "#Struct.#T", lookup: func(val cue.Value) cue.Value { // Locate Struct i, _ := val.Fields(cue.Definitions(true)) if !i.Next() { t.Fatal("no fields") } // Locate b, the second field i, _ = i.Value().Fields(cue.Definitions(true), cue.Optional(true)) for range 2 { if !i.Next() { t.Fatal("no fields") } } v := i.Value() return v }, }, { input: ` package foo #A: #B: #T #T: { a: #S.#U #S: #U: {} } `, want: "#T.#S.#U", lookup: func(val cue.Value) cue.Value { f, _ := val.LookupField("#A") f, _ = f.Value.LookupField("#B") v := f.Value v = cue.Dereference(v) v = v.Lookup("a") return v }, }, { // TODO: record additionalItems in list input: ` package foo #A: #B: #T #T: { a: [...#S] #S: {} } `, want: "#T.#S", lookup: func(val cue.Value) cue.Value { f, _ := val.LookupField("#A") f, _ = f.Value.LookupField("#B") v := f.Value v = cue.Dereference(v) v, _ = v.Lookup("a").Elem() return v }, }, { input: ` #A: { b: #T } #T: { a: #S #S: {} } `, want: "#T.#S", lookup: func(val cue.Value) cue.Value { f, _ := val.LookupField("#A") v := f.Value.Lookup("b") v = cue.Dereference(v) v = v.Lookup("a") return v }, }, { input: ` #Tracing: { #T: { address?: string } #S: { ip?: string } close({}) | close({ t: #T }) | close({ s: #S }) } #X: {} #X // Disconnect top-level struct from the one visible by close. `, want: "#Tracing.#T", lookup: func(val cue.Value) cue.Value { f, _ := val.LookupField("#Tracing") v := f.Value.Eval() _, args := v.Expr() v = args[1] v = v.Lookup("t") return v }, }, { input: ` x: { if true { v: a } } a: b b: 2 `, want: "b", lookup: func(val cue.Value) cue.Value { v := val.LookupPath(cue.ParsePath("x.v")) v = cue.Dereference(v) return v }, }, { input: ` package foo #A:{ if true { #B: #T } } #T: { a: #S.#U #S: #U: {} } `, want: "#T.#S.#U", lookup: func(val cue.Value) cue.Value { f, _ := val.LookupField("#A") f, _ = f.Value.LookupField("#B") v := f.Value v = cue.Dereference(v) v = v.Lookup("a") return v }, }} for _, tc := range testCases { if tc.skip { continue } cuetdtest.FullMatrix.Run(t, "", func(t *testing.T, m *cuetdtest.M) { ctx := m.CueContext() val := ctx.CompileString(tc.input, cue.Filename("in")) v := tc.lookup(val) gotVal, ref := v.ReferencePath() if gotVal != val { t.Error("reference not in original instance") } gotPath := strings.Join(cue.PathToStrings(ref), ".") if gotPath != tc.want { t.Errorf("got path %s; want %s", gotPath, tc.want) } x, p := v.ReferencePath() if x != val { t.Error("reference not in original instance") } gotPath = p.String() if gotPath != tc.want { t.Errorf("got path %s; want %s", gotPath, tc.want) } }) } } // func TestReferences(t *testing.T) { // config1 := ` // a: { // b: 3 // } // c: { // d: a.b // e: c.d // f: a // } // ` // config2 := ` // a: { c: 3 } // b: { c: int, d: 4 } // r: (a & b).c // c: {args: s1 + s2}.args // s1: string // s2: string // d: ({arg: b}).arg.c // e: f.arg.c // f: {arg: b} // ` // testCases := []struct { // config string // in string // out string // }{ // {config1, "c.d", "a.b"}, // {config1, "c.e", "c.d"}, // {config1, "c.f", "a"}, // {config2, "r", "a.c b.c"}, // {config2, "c", "s1 s2"}, // // {config2, "d", "b.c"}, // TODO: make this work as well. // {config2, "e", "f.arg.c"}, // TODO: should also report b.c. // } // for _, tc := range testCases { // t.Run(tc.in, func(t *testing.T) { // ctx, st := compileFile(t, tc.config) // v := newValueRoot(ctx, st) // for _, k := range strings.Split(tc.in, ".") { // obj, err := v.structValFull(ctx) // if err != nil { // t.Fatal(err) // } // v = obj.Lookup(k) // } // got := []string{} // for _, r := range v.References() { // got = append(got, strings.Join(r, ".")) // } // want := strings.Split(tc.out, " ") // if !reflect.DeepEqual(got, want) { // t.Errorf("got %v; want %v", got, want) // } // }) // } // } func checkErr(t *testing.T, err error, str, name string) bool { t.Helper() if err == nil { if str != "" { t.Errorf(`err:%s: got ""; want %q`, name, str) } return true } return checkFailed(t, err, str, name) } func checkFatal(t *testing.T, err error, str, name string) { t.Helper() if !checkFailed(t, err, str, name) { t.SkipNow() } } func checkFailed(t *testing.T, err error, str, name string) bool { t.Helper() if err != nil { got := err.Error() if str == "" { t.Fatalf(`err:%s: got %q; want ""`, name, got) } if !strings.Contains(got, str) { t.Errorf(`err:%s: got %q; want %q`, name, got, str) } return false } return true } func TestExpr(t *testing.T) { testCases := []struct { input string want string }{{ input: "v: 3", want: "3", }, { input: "v: 3 + 4", want: "+(3 4)", }, { input: "v: !a, a: bool", want: `!(.(〈〉 "a"))`, }, { input: "v: !a, a: 3", // TODO: Should still look up. want: `!(.(〈〉 "a"))`, }, { input: "v: 1 | 2 | 3 | *4", want: "|(1 2 3 4)", }, { input: "v: 2 & 5", // Allow even with error. want: "&(2 5)", }, { input: "v: 2 | 5", want: "|(2 5)", }, { input: "v: 2 && 5", want: "&&(2 5)", }, { input: "v: 2 || 5", want: "||(2 5)", }, { input: "v: 2 == 5", want: "==(2 5)", }, { input: "v: !b, b: true", want: `!(.(〈〉 "b"))`, }, { input: "v: 2 != 5", want: "!=(2 5)", }, { input: "v: <5", want: "<(5)", }, { input: "v: 2 <= 5", want: "<=(2 5)", }, { input: "v: 2 > 5", want: ">(2 5)", }, { input: "v: 2 >= 5", want: ">=(2 5)", }, { input: "v: 2 =~ 5", want: "=~(2 5)", }, { input: "v: 2 !~ 5", want: "!~(2 5)", }, { input: "v: 2 + 5", want: "+(2 5)", }, { input: "v: 2 - 5", want: "-(2 5)", }, { input: "v: 2 * 5", want: "*(2 5)", }, { input: "v: 2 / 5", want: "/(2 5)", }, { input: "v: 2 quo 5", want: "quo(2 5)", }, { input: "v: 2 rem 5", want: "rem(2 5)", }, { input: "v: 2 div 5", want: "div(2 5)", }, { input: "v: 2 mod 5", want: "mod(2 5)", }, { input: "v: a.b, a: b: 4", want: `.(.(〈〉 "a") "b")`, }, { input: `v: a["b"], a: b: 3 `, want: `[](.(〈〉 "a") "b")`, }, { input: "v: a[2:5], a: [1, 2, 3, 4, 5]", want: `[:](.(〈〉 "a") 2 5)`, }, { input: "v: len([])", want: "()(len [])", }, { input: "v: a.b, a: { b: string }", want: `.(.(〈〉 "a") "b")`, }, { input: `v: "Hello, \(x)! Welcome to \(place)", place: string, x: string`, want: `\()("Hello, " .(〈〉 "x") "! Welcome to " .(〈〉 "place") "")`, }, { // Split out the reference, but ensure the split-off outer struct // remains valid. input: `v: { a, #b: 1 }, a: 2`, want: `&(.(〈〉 "a") {int,#b:1})`, }, { // Result is an error, no need to split off. input: `v: { a, b: 1 }, a: 2`, want: `&(.(〈〉 "a") {b:1})`, }, { // Don't split of concrete values. input: `v: { "foo", #def: 1 }`, want: `{"foo",#def:1}`, }, { input: `v: { {} | { a: #A, b: #B}, #A: {} | { c: int} }, #B: int | bool`, want: `&(|({} {a:#A,b:#B}) {#A:({}|{c:int})})`, }, { input: `v: { {c: a}, b: a }, a: int`, want: `&({c:a} {b:a})`, }, { input: `v: [...number] | *[1, 2, 3]`, // Filter defaults that are subsumed by another value. want: `[...number]`, }, { input: `v: or([1, 2, 3])`, want: `|(1 2 3)`, }, { input: `v: or([])`, want: `_|_(empty list in call to or)`, }, { input: `v: and([1, 2, 3])`, want: `&(1 2 3)`, }, { input: `v: and([])`, want: `_`, }, { //Issue #1245 input: ` x: *4 | int v: x | *7 `, want: `|(.(〈〉 "x") 7)`, }, { // Issue #1119 // Unwrap single embedded values. input: `v: {>30}`, want: `>(30)`, }, { input: `v: {>30, <40}`, want: `&(>(30) <(40))`, }, { input: `a: string, if true { v: a }`, want: `.(〈〉 "a")`, }} for _, tc := range testCases { cuetdtest.FullMatrix.Run(t, tc.input, func(t *testing.T, m *cuetdtest.M) { v := getValue(m, tc.input).Lookup("v") got := exprStr(v) if got != tc.want { t.Errorf("\n got %v;\nwant %v", got, tc.want) } }) } } func exprStr(v cue.Value) string { op, operands := v.Expr() if op == cue.NoOp { return compactRawStr(operands[0]) } s := op.String() s += "(" for i, v := range operands { if i > 0 { s += " " } s += exprStr(v) } s += ")" return s } func compactRawStr(v cue.Value) string { ctx := cue.ValueCtx(v) cfg := &debug.Config{Compact: true, Raw: true} return debug.NodeString(ctx, cue.ValueVertex(v), cfg) } cue-lang-cue-db9cc73/cue/version.go000066400000000000000000000015541474664451600172750ustar00rootroot00000000000000// Copyright 2024 The CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue import "cuelang.org/go/internal/cueversion" // LanguageVersion returns the CUE language version. // This determines the latest version of CUE that // is understood by the evaluator and module code. func LanguageVersion() string { return cueversion.LanguageVersion() } cue-lang-cue-db9cc73/cuego/000077500000000000000000000000001474664451600156025ustar00rootroot00000000000000cue-lang-cue-db9cc73/cuego/cuego.go000066400000000000000000000133201474664451600172320ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cuego import ( "fmt" "reflect" "sync" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/parser" "cuelang.org/go/internal/value" ) // DefaultContext is the shared context used with top-level functions. var DefaultContext = &Context{} // MustConstrain is like Constrain, but panics if there is an error. func MustConstrain(x interface{}, constraints string) { if err := Constrain(x, constraints); err != nil { panic(err) } } // Constrain associates the given CUE constraints with the type of x or // reports an error if the constraints are invalid or not compatible with x. // // Constrain works across package boundaries and is typically called in the // package defining the type. Use a Context to apply constraints locally. func Constrain(x interface{}, constraints string) error { return DefaultContext.Constrain(x, constraints) } // Validate is a wrapper for Validate called on the global context. func Validate(x interface{}) error { return DefaultContext.Validate(x) } // Complete sets previously undefined values in x that can be uniquely // determined form the constraints defined on the type of x such that validation // passes, or returns an error, without modifying anything, if this is not // possible. // // Complete does a JSON round trip. This means that data not preserved in such a // round trip, such as the location name of a time.Time, is lost after a // successful update. func Complete(x interface{}) error { return DefaultContext.Complete(x) } // A Context holds type constraints that are only applied within a given // context. // Global constraints that are defined at the time a constraint is // created are applied as well. type Context struct { typeCache sync.Map // map[reflect.Type]cue.Value } // Validate checks whether x validates against the registered constraints for // the type of x. // // Constraints for x can be defined as field tags or through the Register // function. func (c *Context) Validate(x interface{}) error { a := c.load(x) v, err := fromGoValue(x, false) if err != nil { return err } v = a.Unify(v) if err := v.Validate(); err != nil { return err } // TODO: validate all values are concrete. (original value subsumes result?) return nil } // Complete sets previously undefined values in x that can be uniquely // determined form the constraints defined on the type of x such that validation // passes, or returns an error, without modifying anything, if this is not // possible. // // A value is considered undefined if it is pointer type and is nil or if it // is a field with a zero value and a json tag with the omitempty tag. // Complete does a JSON round trip. This means that data not preserved in such a // round trip, such as the location name of a time.Time, is lost after a // successful update. func (c *Context) Complete(x interface{}) error { a := c.load(x) v, err := fromGoValue(x, true) if err != nil { return err } v = a.Unify(v) if err := v.Validate(cue.Concrete(true)); err != nil { return err } return v.Decode(x) } func (c *Context) load(x interface{}) cue.Value { t := reflect.TypeOf(x) if value, ok := c.typeCache.Load(t); ok { return value.(cue.Value) } // fromGoType should prevent the work is done no more than once, but even // if it is, there is no harm done. v := fromGoType(x) c.typeCache.Store(t, v) return v } // TODO: should we require that Constrain be defined on exported, // named types types only? // Constrain associates the given CUE constraints with the type of x or reports // an error if the constraints are invalid or not compatible with x. func (c *Context) Constrain(x interface{}, constraints string) error { c.load(x) // Ensure fromGoType is called outside of lock. mutex.Lock() defer mutex.Unlock() expr, err := parser.ParseExpr(fmt.Sprintf("<%T>", x), constraints) if err != nil { return err } v := runtime.BuildExpr(expr) if v.Err() != nil { return err } typ := c.load(x) v = typ.Unify(v) if err := v.Validate(); err != nil { return err } t := reflect.TypeOf(x) c.typeCache.Store(t, v) return nil } var ( mutex sync.Mutex runtime = cuecontext.New() ) // fromGoValue converts a Go value to CUE func fromGoValue(x interface{}, nilIsNull bool) (v cue.Value, err error) { // TODO: remove the need to have a lock here. We could use a new index (new // Instance) here as any previously unrecognized field can never match an // existing one and can only be merged. mutex.Lock() v = value.FromGoValue(runtime, x, nilIsNull) mutex.Unlock() if err := v.Err(); err != nil { return v, err } return v, nil // // This should be equivalent to the following: // b, err := json.Marshal(x) // if err != nil { // return v, err // } // expr, err := parser.ParseExpr(fset, "", b) // if err != nil { // return v, err // } // mutex.Lock() // v = instance.Eval(expr) // mutex.Unlock() // return v, nil } func fromGoType(x interface{}) cue.Value { // TODO: remove the need to have a lock here. We could use a new index (new // Instance) here as any previously unrecognized field can never match an // existing one and can only be merged. mutex.Lock() v := value.FromGoType(runtime, x) mutex.Unlock() return v } cue-lang-cue-db9cc73/cuego/cuego_test.go000066400000000000000000000074431474664451600203020ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cuego import ( "reflect" "testing" ) type Sum struct { A int `cue:"C-B" json:",omitempty"` B int `cue:"C-A" json:",omitempty"` C int `cue:"A+B & >=5" json:",omitempty"` } func checkErr(t *testing.T, got error, want string) { t.Helper() if (got == nil) != (want == "") { t.Errorf("error: got %v; want %v", got, want) } } func TestValidate(t *testing.T) { fail := "some error" testCases := []struct { name string value interface{} constraints string err string }{{ name: "Sum", value: Sum{A: 1, B: 4, C: 5}, }, { name: "*Sum", value: &Sum{A: 1, B: 4, C: 5}, }, { name: "*Sum: incorrect sum", value: &Sum{A: 1, B: 4, C: 6}, err: fail, }, { name: "*Sum: field C is too low", value: &Sum{A: 1, B: 3, C: 4}, err: fail, }, { name: "*Sum: nil value", value: (*Sum)(nil), // }, { // // TODO: figure out whether this constraint should constrain it // // to a struct or not. // name: "*Sum: nil disallowed by constraint", // value: (*Sum)(nil), // constraints: "!=null", // err: fail, }, { // Not a typical constraint, but it is possible. name: "string list", value: []string{"a", "b", "c"}, constraints: `[_, "b", ...]`, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { c := &Context{} if tc.constraints != "" { err := c.Constrain(tc.value, tc.constraints) if err != nil { t.Fatal(err) } } err := c.Validate(tc.value) checkErr(t, err, tc.err) }) } } func TestUpdate(t *testing.T) { type sump struct { A *int `cue:"C-B"` B *int `cue:"C-A"` C *int `cue:"A+B"` } one := 1 two := 2 fail := "some error" _ = fail _ = one testCases := []struct { name string value interface{} result interface{} constraints string err string }{{ name: "*Sum", value: &Sum{A: 1, B: 4, C: 5}, result: &Sum{A: 1, B: 4, C: 5}, }, { name: "*Sum", value: &Sum{A: 1, B: 4}, result: &Sum{A: 1, B: 4, C: 5}, }, { name: "*sump", value: &sump{A: &one, B: &one}, result: &sump{A: &one, B: &one, C: &two}, }, { name: "*Sum: backwards", value: &Sum{B: 4, C: 8}, result: &Sum{A: 4, B: 4, C: 8}, }, { name: "*Sum: sum too low", value: &Sum{A: 1, B: 3}, result: &Sum{A: 1, B: 3}, // Value should not be updated err: fail, }, { name: "*Sum: sum underspecified", value: &Sum{A: 1}, result: &Sum{A: 1}, // Value should not be updated err: fail, }, { name: "Sum: cannot modify", value: Sum{A: 3, B: 4, C: 7}, result: Sum{A: 3, B: 4, C: 7}, err: fail, }, { name: "*Sum: cannot update nil value", value: (*Sum)(nil), result: (*Sum)(nil), err: fail, }, { name: "cannot modify slice", value: []string{"a", "b", "c"}, result: []string{"a", "b", "c"}, err: fail, }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { c := &Context{} if tc.constraints != "" { err := c.Constrain(tc.value, tc.constraints) if err != nil { t.Fatal(err) } } err := c.Complete(tc.value) checkErr(t, err, tc.err) if !reflect.DeepEqual(tc.value, tc.result) { t.Errorf("value:\n got: %#v;\nwant: %#v", tc.value, tc.result) } }) } } cue-lang-cue-db9cc73/cuego/doc.go000066400000000000000000000045331474664451600167030ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package cuego allows using CUE constraints in Go programs. // // CUE constraints can be used to validate Go types as well as fill out // missing struct fields that are implied from the constraints and the values // already defined by the struct value. // // CUE constraints can be added through field tags or by associating // CUE code with a Go type. The field tags method follows the usual // Go pattern: // // type Sum struct { // A int `cue:"C-B" json:",omitempty"` // B int `cue:"C-A" json:",omitempty"` // C int `cue:"A+B" json:",omitempty"` // } // // func main() { // fmt.Println(cuego.Validate(&Sum{A: 1, B: 5, C: 6})) // } // // AddConstraints allows annotating Go types with any CUE constraints. // // # Validating Go Values // // To check whether a struct's values satisfy its constraints, call Validate: // // if err := cuego.Validate(p); err != nil { // return err // } // // Validation assumes that all values are filled in correctly and will not // infer values. To automatically infer values, use Complete. // // # Completing Go Values // // Package cuego can also be used to infer undefined values from a set of // CUE constraints, for instance to fill out fields in a struct. A value // is considered undefined if it is a nil pointer type or if it is a zero // value and there is a JSON field tag with the omitempty flag. // A Complete will implicitly validate a struct. package cuego // The first goal of this package is to get the semantics right. After that, // there are a lot of performance gains to be made: // - cache the type info extracted during value (as opposed to type) conversion // - remove the usage of mutex for value conversions // - avoid the JSON round trip for Decode, as used in Complete // - generate native code for validating and updating cue-lang-cue-db9cc73/cuego/examples_test.go000066400000000000000000000057321474664451600210150ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cuego_test import ( "fmt" "strings" "cuelang.org/go/cue/errors" "cuelang.org/go/cuego" ) func ExampleComplete_structTag() { type Sum struct { A int `cue:"C-B" json:",omitempty"` B int `cue:"C-A" json:",omitempty"` C int `cue:"A+B" json:",omitempty"` } a := Sum{A: 1, B: 5} err := cuego.Complete(&a) fmt.Printf("completed: %#v (err: %v)\n", a, err) a = Sum{A: 2, C: 8} err = cuego.Complete(&a) fmt.Printf("completed: %#v (err: %v)\n", a, err) a = Sum{A: 2, B: 3, C: 8} err = cuego.Complete(&a) fmt.Println(errMsg(err)) //Output: // completed: cuego_test.Sum{A:1, B:5, C:6} (err: ) // completed: cuego_test.Sum{A:2, B:6, C:8} (err: ) // 2 errors in empty disjunction: // conflicting values null and {A:2,B:3,C:8} (mismatched types null and struct) // A: conflicting values 5 and 2 } func ExampleConstrain() { type Config struct { Filename string OptFile string `json:",omitempty"` MaxCount int MinCount int // TODO: show a field with time.Time } err := cuego.Constrain(&Config{}, `{ let jsonFile = =~".json$" // Filename must be defined and have a .json extension Filename: jsonFile // OptFile must be undefined or be a file name with a .json extension OptFile?: jsonFile MinCount: >0 & <=MaxCount MaxCount: <=10_000 }`) fmt.Println("error:", errMsg(err)) fmt.Println("validate:", errMsg(cuego.Validate(&Config{ Filename: "foo.json", MaxCount: 1200, MinCount: 39, }))) fmt.Println("validate:", errMsg(cuego.Validate(&Config{ Filename: "foo.json", MaxCount: 12, MinCount: 39, }))) fmt.Println("validate:", errMsg(cuego.Validate(&Config{ Filename: "foo.jso", MaxCount: 120, MinCount: 39, }))) // TODO(errors): fix bound message (should be "does not match") //Output: // error: nil // validate: nil // validate: 2 errors in empty disjunction: // conflicting values null and {Filename:"foo.json",MaxCount:12,MinCount:39} (mismatched types null and struct) // MinCount: invalid value 39 (out of bound <=12) // validate: 2 errors in empty disjunction: // conflicting values null and {Filename:"foo.jso",MaxCount:120,MinCount:39} (mismatched types null and struct) // Filename: invalid value "foo.jso" (out of bound =~".json$") } func errMsg(err error) string { a := []string{} for _, err := range errors.Errors(err) { a = append(a, err.Error()) } s := strings.Join(a, "\n") if s == "" { return "nil" } return s } cue-lang-cue-db9cc73/doc/000077500000000000000000000000001474664451600152455ustar00rootroot00000000000000cue-lang-cue-db9cc73/doc/cmd/000077500000000000000000000000001474664451600160105ustar00rootroot00000000000000cue-lang-cue-db9cc73/doc/cmd/cue.md000066400000000000000000000007251474664451600171120ustar00rootroot00000000000000# `cue` command reference `cue help` gives information about the various `cue` commands available, as well as additional help topics. For example `cue help import` gives information about how to convert other formats like JSON and YAML to CUE, and `cue help filetypes` describes the `cue` command's support for various file types. We do plan to provide a web-based version of these various help topics, something that is tracked by [#9](https://cuelang.org/issue/9). cue-lang-cue-db9cc73/doc/ref/000077500000000000000000000000001474664451600160215ustar00rootroot00000000000000cue-lang-cue-db9cc73/doc/ref/impl.md000066400000000000000000000322161474664451600173100ustar00rootroot00000000000000# Implementing CUE > NOTE: this is a working document attempting to describe CUE in a way > relatable to existing graph unification systems. It is mostly > redundant to [the spec](./spec.md). Unless one is interested in > understanding how to implement CUE or how it relates to the existing > body of research, read the spec instead. CUE is modeled after typed feature structure and graph unification systems such as LKB. There is a wealth of research related to such systems and graph unification in general. This document describes the core semantics of CUE in a notation that allows relating it to this existing body of research. ## Background CUE was inspired by a formalism known as typed attribute structures [Carpenter 1992] or typed feature structures [Copestake 2002], which are used in linguistics to encode grammars and lexicons. Being able to effectively encode large amounts of data in a rigorous manner, this formalism seemed like a great fit for large-scale configuration. Although CUE configurations are specified as trees, not graphs, implementations can benefit from considering them as graphs when dealing with cycles, and effectively turning them into graphs when applying techniques like structure sharing. Dealing with cycles is well understood for typed attribute structures and as CUE configurations are formally closely related to them, we can benefit from this knowledge without reinventing the wheel. ## Formal Definition A CUE configuration can be defined in terms of constraints, which are analogous to typed attribute structures referred to above. ### Definition of basic values > A _basic value_ is any CUE value that is not a struct (or, by > extension, a list). > All basic values are partially ordered in a lattice, such that for any > basic value `a` and `b` there is a unique greatest lower bound > defined for the subsumption relation `a ⊑ b`. ``` Basic values null true bool 3.14 string "Hello" >=0 <8 re("Hello .*!") ``` The basic values correspond to their respective types defined earlier. Struct (and by extension lists), are represented by the abstract notion of a typed feature structure. Each node in a configuration, including the root node, is associated with a constraint. ### Definition of a typed feature structures and substructures > A typed feature structure_ defined for a finite set of labels `Label` > is directed acyclic graph with labeled > arcs and values, represented by a tuple `C = `, where > > 1. `Q` is the finite set of nodes, > 1. `q0 ∈ Q`, is the root node, > 1. `υ: Q → T` is the total node typing function, > for a finite set of possible terms `T`. > 1. `δ: Q × Label → Q` is the partial feature function, > > subject to the following conditions: > > 1. there is no node `q` or label `l` such that `δ(q, l) = q0` (root) > 2. for every node `q` in `Q` there is a path `π` (i.e. a sequence of > members of Label) such that `δ(q0, π) = q` (unique root, correctness) > 3. there is no node `q` or non-empty path `π` such that `δ(q, π) = q` (no cycles) > > where `δ` is extended to be defined on paths as follows: > > 1. `δ(q, ϵ) = q`, where `ϵ` is the empty path > 2. `δ(q, l∙π) = δ(δ(q, l), π)` > > The _substructures_ of a typed feature structure are the > typed feature structures rooted at each node in the structure. > > The set of all possible typed feature structures for a given label > set is denoted as `𝒞``Label`. > > The set of _terms_ for label set `Label` is recursively defined as > > 1. every basic value: `P ⊆ T` > 1. every constraint in `𝒞``Label` is a term: `𝒞``Label`` ⊆ T` > a _reference_ may refer to any substructure of `C`. > 1. for every `n` values `t₁, ..., tₙ`, and every `n`-ary function symbol > `f ∈ F_n`, the value `f(t₁,...,tₙ) ∈ T`. > This definition has been taken and modified from [Carpenter, 1992] and [Copestake, 2002]. Without loss of generality, we will henceforth assume that the given set of labels is constant and denote `𝒞``Label` as `𝒞`. In CUE configurations, the abstract constraints implicated by `υ` are CUE expressions. Literal structs can be treated as part of the original typed feature structure and do not need evaluation. Any other expression is evaluated and unified with existing values of that node. References in expressions refer to other nodes within the `C` and represent a copy of the substructure `C'` of `C` rooted at these nodes. Any references occurring in terms assigned to nodes of `C'` are be updated to point to the equivalent node in a copy of `C'`. The functions defined by `F` correspond to the binary and unary operators and interpolation construct of CUE, as well as builtin functions. CUE allows duplicate labels within a struct, while the definition of typed feature structures does not. A duplicate label `l` with respective values `a` and `b` is represented in a constraint as a single label with term `&(a, b)`, the unification of `a` and `b`. Multiple labels may be recursively combined in any order. ### Definition of subsumption and unification on typed attribute structure > For a given collection of constraints `𝒞`, > we define `π ≡``C` `π'` to mean that typed feature structure `C ∈ 𝒞` > contains path equivalence between the paths `π` and `π'` > (i.e. `δ(q0, π) = δ(q0, π')`, where `q0` is the root node of `C`); > and `𝒫``C``(π) = c` to mean that > the typed feature structure at the path `π` in `C` > is `c` (i.e. `𝒫``C``(π) = c` if and only if `υ(δ(q0, π)) == c`, > where `q0` is the root node of `C`). > Subsumption is then defined as follows: > `C ∈ 𝒞` subsumes `C' ∈ 𝒞`, written `C' ⊑ C`, if and only if: > > - `π ≡``C` `π'` implies `π ≡``C'` `π'` > - `𝒫``C``(π) = c` implies`𝒫``C'``(π) = c` and `c' ⊑ c` > > The unification of `C` and `C'`, denoted `C ⊓ C'`, > is the greatest lower bound of `C` and `C'` in `𝒞` ordered by subsumption. Like with the subsumption relation for basic values, the subsumption relation for constraints determines the mutual placement of constraints within the partial order of all values. ### Evaluation function > The evaluation function is given by `E: T -> 𝒞`. > The unification of two typed feature structures is evaluated as defined above. > All other functions are evaluated according to the definitions found earlier > in this spec. > An error is indicated by `_|_`. #### Definition of well-formedness > We say that a given typed feature structure `C = ∈ 𝒞` is > a _well-formed_ typed feature structure if and only if for all nodes `q ∈ Q`, > the substructure `C'` rooted at `q`, > is such that `E(υ(q)) ∈ 𝒞` and `C' = ⊑ E(υ(q))`. The _evaluation_ of a CUE configuration represented by `C` is defined as the process of making `C` well-formed. ### References Theory: - [1992] Bob Carpenter, "The logic of typed feature structures."; Cambridge University Press, ISBN:0-521-41932-8 - [2002] Ann Copestake, "Implementing Typed Feature Structure Grammars."; CSLI Publications, ISBN 1-57586-261-1 Some graph unification algorithms: - [1985] Fernando C. N. Pereira, "A structure-sharing representation for unification-based grammar formalisms."; In Proc. of the 23rd Annual Meeting of the Association for Computational Linguistics. Chicago, IL - [1991] H. Tomabechi, "Quasi-destructive graph unifications.."; In Proceedings of the 29th Annual Meeting of the ACL. Berkeley, CA - [1992] Hideto Tomabechi, "Quasi-destructive graph unifications with structure- sharing."; In Proceedings of the 15th International Conference on Computational Linguistics (COLING-92), Nantes, France. - [2001] Marcel van Lohuizen, "Memory-efficient and thread-safe quasi-destructive graph unification."; In Proceedings of the 38th Meeting of the Association for Computational Linguistics. Hong Kong, China. ## Implementation The _evaluation_ of a CUE configuration `C` is defined as the process of making `C` well-formed. This section does not define any operational semantics. As the unification operation is communitive, transitive, and reflexive, implementations have a considerable amount of leeway in choosing an evaluation strategy. Although most algorithms for the unification of typed attribute structure that have been proposed are near `O(n)`, there can be considerable performance benefits of choosing one of the many proposed evaluation strategies over the other. Implementations will need to be verified against the above formal definition. ### Constraint functions A _constraint function_ is a unary function `f` which for any input `a` only returns values that are an instance of `a`. For instance, the constraint function `f` for `string` returns `"foo"` for `f("foo")` and `_|_` for `f(1)`. Constraint functions may take other constraint functions as arguments to produce a more restricting constraint function. For instance, the constraint function `f` for `<=8` returns `5` for `f(5)`, `>=5 & <=8` for `f(>=5)`, and `_|_` for `f("foo")`. Constraint functions play a special role in unification. The unification function `&(a, b)` is defined as - `a & b` if `a` and `b` are two atoms - `a & b` if `a` and `b` are two nodes, respresenting struct - `a(b)` or `b(a)` if either `a` or `b` is a constraint function, respectively. Implementations are free to pick which constraint function is applied if both `a` and `b` are constraint functions, as the properties of unification will ensure this produces identical results. ### References A distinguising feature of CUE's unification algorithm is the use of references. In conventional graph unification for typed feature structures, the structures that are unified into the existing graph are independent and pre-evaluated. In CUE, the typed feature structures indicated by references may still need to be evaluated. Some conventional evaluation strategies may not cope well with references that refer to each other. The simple solution is to deploy a breadth-first evaluation strategy, rather than the more traditional depth-first approach. Other approaches are possible, however, and implementations are free to choose which approach is deployed. cue-lang-cue-db9cc73/doc/ref/spec.md000066400000000000000000002715071474664451600173110ustar00rootroot00000000000000 # The CUE Language Specification ## Introduction This is a reference manual for the CUE data constraint language. CUE, pronounced cue or Q, is a general-purpose and strongly typed constraint-based language. It can be used for data templating, data validation, code generation, scripting, and many other applications involving structured data. The CUE tooling, layered on top of CUE, provides a general purpose scripting language for creating scripts as well as simple servers, also expressed in CUE. CUE was designed with cloud configuration and related systems in mind, but is not limited to this domain. It derives its formalism from relational programming languages. This formalism allows for managing and reasoning over large amounts of data in a straightforward manner. The grammar is compact and regular, allowing for easy analysis by automatic tools such as integrated development environments. This document is maintained by mpvl@golang.org. CUE has a lot of similarities with the Go language. This document draws heavily from the Go specification as a result. CUE draws its influence from many languages. Its main influences were BCL/GCL (internal to Google), LKB (LinGO), Go, and JSON. Others are Swift, Typescript, Javascript, Prolog, NCL (internal to Google), Jsonnet, HCL, Flabbergast, Nix, JSONPath, Haskell, Objective-C, and Python. ## Notation The syntax is specified using Extended Backus-Naur Form (EBNF): ``` Production = production_name "=" [ Expression ] "." . Expression = Alternative { "|" Alternative } . Alternative = Term { Term } . Term = production_name | token [ "…" token ] | Group | Option | Repetition . Group = "(" Expression ")" . Option = "[" Expression "]" . Repetition = "{" Expression "}" . ``` Productions are expressions constructed from terms and the following operators, in increasing precedence: ``` | alternation () grouping [] option (0 or 1 times) {} repetition (0 to n times) ``` Lower-case production names are used to identify lexical tokens. Non-terminals are in CamelCase. Lexical tokens are enclosed in double quotes `""` or back quotes ` `` `. The form `a … b` represents the set of characters from a through b as alternatives. The horizontal ellipsis `…` is also used elsewhere in the spec to informally denote various enumerations or code snippets that are not further specified. The character `…` (as opposed to the three characters `...`) is not a token of the CUE language. ## Source code representation Source code is Unicode text encoded in UTF-8. Unless otherwise noted, the text is not canonicalized, so a single accented code point is distinct from the same character constructed from combining an accent and a letter; those are treated as two code points. For simplicity, this document will use the unqualified term character to refer to a Unicode code point in the source text. Each code point is distinct; for instance, upper and lower case letters are different characters. Implementation restriction: For compatibility with other tools, a compiler may disallow the NUL character (U+0000) in the source text. Implementation restriction: For compatibility with other tools, a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF) if it is the first Unicode code point in the source text. A byte order mark may be disallowed anywhere else in the source. ### Characters The following terms are used to denote specific Unicode character classes: ``` newline = /* the Unicode code point U+000A */ . unicode_char = /* an arbitrary Unicode code point except newline */ . unicode_letter = /* a Unicode code point classified as "Letter" */ . unicode_digit = /* a Unicode code point classified as "Number, decimal digit" */ . ``` In The Unicode Standard 8.0, Section 4.5 "General Category" defines a set of character categories. CUE treats all characters in any of the Letter categories Lu, Ll, Lt, Lm, or Lo as Unicode letters, and those in the Number category Nd as Unicode digits. ### Letters and digits The underscore character `_` (U+005F) is considered a letter. ``` letter = unicode_letter | "_" | "$" . decimal_digit = "0" … "9" . binary_digit = "0" … "1" . octal_digit = "0" … "7" . hex_digit = "0" … "9" | "A" … "F" | "a" … "f" . ``` ## Lexical elements ### Comments Comments serve as program documentation. CUE supports line comments that start with the character sequence `//` and stop at the end of the line. A comment cannot start inside a string literal or inside a comment. A comment acts like a newline. ### Tokens Tokens form the vocabulary of the CUE language. There are four classes: identifiers, keywords, operators and punctuation, and literals. White space, formed from spaces (U+0020), horizontal tabs (U+0009), carriage returns (U+000D), and newlines (U+000A), is ignored except as it separates tokens that would otherwise combine into a single token. Also, a newline or end of file may trigger the insertion of a comma. While breaking the input into tokens, the next token is the longest sequence of characters that form a valid token. ### Commas The formal grammar uses commas `,` as terminators in a number of productions. CUE programs may omit most of these commas using the following rules: When the input is broken into tokens, a comma is automatically inserted into the token stream immediately after a line's final token if that token is - an identifier, keyword, or bottom - a number or string literal, including an interpolation - one of the characters `)`, `]`, `}`, or `?` - an ellipsis `...` Although commas are automatically inserted, the parser will require explicit commas between two list elements. To reflect idiomatic use, examples in this document elide commas using these rules. ### Identifiers Identifiers name entities such as fields and aliases. An identifier is a sequence of one or more letters (which includes `_` and `$`) and digits, optionally preceded by `#` or `_#`. It may not be `_` or `$`. The first character in an identifier, or after an `#` if it contains one, must be a letter. Identifiers starting with a `#` or `_` are reserved for definitions and hidden fields. ``` identifier = [ "#" | "_#" ] letter { letter | unicode_digit } . ``` ``` a _x9 fieldName αβ ``` Some identifiers are [predeclared](#predeclared-identifiers). ### Keywords CUE has a limited set of keywords. In addition, CUE reserves all identifiers starting with `__` (double underscores) as keywords. These are typically targets of pre-declared identifiers. All keywords may be used as labels (field names). Unless noted otherwise, they can also be used as identifiers to refer to the same name. #### Values The following keywords are values. ``` null true false ``` These can never be used to refer to a field of the same name. This restriction is to ensure compatibility with JSON configuration files. #### Preamble The following keywords are used at the preamble of a CUE file. After the preamble, they may be used as identifiers to refer to namesake fields. ``` package import ``` #### Comprehension clauses The following keywords are used in comprehensions. ``` for in if let ``` ### Operators and punctuation The following character sequences represent operators and punctuation: ``` + && == < = ( ) - || != > : { } * & =~ <= ? [ ] , / | !~ >= ! _|_ ... . ``` ### Numeric literals There are several kinds of numeric literals. ``` int_lit = decimal_lit | si_lit | octal_lit | binary_lit | hex_lit . decimal_lit = "0" | ( "1" … "9" ) { [ "_" ] decimal_digit } . decimals = decimal_digit { [ "_" ] decimal_digit } . si_it = decimals [ "." decimals ] multiplier | "." decimals multiplier . binary_lit = "0b" binary_digit { [ "_" ] binary_digit } . hex_lit = "0" ( "x" | "X" ) hex_digit { [ "_" ] hex_digit } . octal_lit = "0o" octal_digit { [ "_" ] octal_digit } . multiplier = ( "K" | "M" | "G" | "T" | "P" ) [ "i" ] float_lit = decimals "." [ decimals ] [ exponent ] | decimals exponent | "." decimals [ exponent ]. exponent = ( "e" | "E" ) [ "+" | "-" ] decimals . ``` An _integer literal_ is a sequence of digits representing an integer value. An optional prefix sets a non-decimal base: `0o` for octal, `0x` or `0X` for hexadecimal, and `0b` for binary. In hexadecimal literals, letters `a … f` and `A … F` represent values 10 through 15. All integers allow interstitial underscores `_`; these have no meaning and are solely for readability. Integer literals may have an SI or IEC multiplier. Multipliers can be used with fractional numbers. When multiplying a fraction by a multiplier, the result is truncated towards zero if it is not an integer. ``` 42 1.5G // 1_500_000_000 1.3Ki // 1.3 * 1024 = trunc(1331.2) = 1331 170_141_183_460_469_231_731_687_303_715_884_105_727 0xBad_Face 0o755 0b0101_0001 ``` A _decimal floating-point literal_ is a representation of a decimal floating-point value (a _float_). It has an integer part, a decimal point, a fractional part, and an exponent part. The integer and fractional part comprise decimal digits; the exponent part is an `e` or `E` followed by an optionally signed decimal exponent. One of the integer part or the fractional part may be elided; one of the decimal point or the exponent may be elided. ``` 0. 72.40 072.40 // == 72.40 2.71828 1.e+0 6.67428e-11 1E6 .25 .12345E+5 ``` Neither a `float_lit` nor an `si_lit` may appear after a token that is: - an identifier, keyword, or bottom - a number or string literal, including an interpolation - one of the characters `)`, `]`, `}`, `?`, or `.`. ### String and byte sequence literals A string literal represents a string constant obtained from concatenating a sequence of characters. Byte sequences are a sequence of bytes. String and byte sequence literals are character sequences between, respectively, double and single quotes, as in `"bar"` and `'bar'`. Within the quotes, any character may appear except newline and, respectively, unescaped double or single quote. String literals may only be valid UTF-8. Byte sequences may contain any sequence of bytes. Several escape sequences allow arbitrary values to be encoded as ASCII text. An escape sequence starts with an _escape delimiter_, which is `\` by default. The escape delimiter may be altered to be `\` plus a fixed number of hash symbols `#` by padding the start and end of a string or byte sequence literal with this number of hash symbols. There are four ways to represent the integer value as a numeric constant: `\x` followed by exactly two hexadecimal digits; `\u` followed by exactly four hexadecimal digits; `\U` followed by exactly eight hexadecimal digits, and a plain backslash `\` followed by exactly three octal digits. In each case the value of the literal is the value represented by the digits in the corresponding base. Hexadecimal and octal escapes are only allowed within byte sequences (single quotes). Although these representations all result in an integer, they have different valid ranges. Octal escapes must represent a value between 0 and 255 inclusive. Hexadecimal escapes satisfy this condition by construction. The escapes `\u` and `\U` represent Unicode code points so within them some values are illegal, in particular those above `0x10FFFF`. Surrogate halves are allowed, but are translated into their non-surrogate equivalent internally. The three-digit octal (`\nnn`) and two-digit hexadecimal (`\xnn`) escapes represent individual bytes of the resulting string; all other escapes represent the (possibly multi-byte) UTF-8 encoding of individual characters. Thus inside a string literal `\377` and `\xFF` represent a single byte of value `0xFF=255`, while `ÿ`, `\u00FF`, `\U000000FF` and `\xc3\xbf` represent the two bytes `0xc3 0xbf` of the UTF-8 encoding of character `U+00FF`. ``` \a U+0007 alert or bell \b U+0008 backspace \f U+000C form feed \n U+000A line feed or newline \r U+000D carriage return \t U+0009 horizontal tab \v U+000b vertical tab \/ U+002f slash (solidus) \\ U+005c backslash \' U+0027 single quote (valid escape only within single quoted literals) \" U+0022 double quote (valid escape only within double quoted literals) ``` The escape `\(` is used as an escape for string interpolation. A `\(` must be followed by a valid CUE Expression, followed by a `)`. A backslash at the end of a line elides the line terminator that follows it. This may not escape the final newline inside a multiline string: that newline is already implicitly elided. All other sequences starting with a backslash are illegal inside literals. ``` escaped_char = `\` { `#` } ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | "/" | `\` | "'" | `"` ) . byte_value = octal_byte_value | hex_byte_value . octal_byte_value = `\` { `#` } octal_digit octal_digit octal_digit . hex_byte_value = `\` { `#` } "x" hex_digit hex_digit . little_u_value = `\` { `#` } "u" hex_digit hex_digit hex_digit hex_digit . big_u_value = `\` { `#` } "U" hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit . unicode_value = unicode_char | little_u_value | big_u_value | escaped_char . interpolation = "\" { `#` } "(" Expression ")" . string_lit = simple_string_lit | multiline_string_lit | simple_bytes_lit | multiline_bytes_lit | `#` string_lit `#` . simple_string_lit = `"` { unicode_value | interpolation } `"` . simple_bytes_lit = `'` { unicode_value | interpolation | byte_value } `'` . multiline_string_lit = `"""` newline { unicode_value | interpolation | newline } newline `"""` . multiline_bytes_lit = "'''" newline { unicode_value | interpolation | byte_value | newline } newline "'''" . ``` Carriage return characters (`\r`) inside string literals are discarded from the string value. ``` 'a\000\xab' '\007' '\377' '\xa' // illegal: too few hexadecimal digits "\n" "\"" 'Hello, world!\n' "Hello, \( name )!" "日本語" "\u65e5本\U00008a9e" '\xff\u00FF' "\uD800" // illegal: surrogate half (TODO: probably should allow) "\U00110000" // illegal: invalid Unicode code point #"This is not an \(interpolation)"# #"This is an \#(interpolation)"# #"The sequence "\U0001F604" renders as \#U0001F604."# ``` These examples all represent the same string: ``` "日本語" // UTF-8 input text '日本語' // UTF-8 input text as byte sequence "\u65e5\u672c\u8a9e" // the explicit Unicode code points "\U000065e5\U0000672c\U00008a9e" // the explicit Unicode code points '\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e' // the explicit UTF-8 bytes ``` If the source code represents a character as two code points, such as a combining form involving an accent and a letter, the result will appear as two code points if placed in a string literal. Strings and byte sequences have a multiline equivalent. Multiline strings are like their single-line equivalent, but allow newline characters. Multiline strings and byte sequences respectively start with a triple double quote (`"""`) or triple single quote (`'''`), immediately followed by a newline, which is discarded from the string contents. The string is closed by a matching triple quote, which must be by itself on a new line, preceded by optional whitespace. The newline preceding the closing quote is discarded from the string contents. The whitespace before a closing triple quote must appear before any non-empty line after the opening quote and will be removed from each of these lines in the string literal. A closing triple quote may not appear in the string. To include it is suffices to escape one of the quotes. ``` """ lily: out of the water out of itself bass picking \ bugs off the moon — Nick Virgilio, Selected Haiku, 1988 """ ``` This represents the same string as: ``` "lily:\nout of the water\nout of itself\n\n" + "bass\npicking bugs\noff the moon\n" + " — Nick Virgilio, Selected Haiku, 1988" ``` ## Values In addition to simple values like `"hello"` and `42.0`, CUE has [structs](#structs). A struct is a map from labels to values, like `{a: 42.0, b: "hello"}`. Structs are CUE's only way of building up complex values; lists, which we will see later, are defined in terms of structs. All possible values are ordered in a lattice, a partial order where every two elements have a single greatest lower bound. A value `a` is an _instance_ of a value `b`, denoted `a ⊑ b`, if `b == a` or `b` is more general than `a`, that is if `a` orders before `b` in the partial order (`⊑` is _not_ a CUE operator). We also say that `b` _subsumes_ `a` in this case. In graphical terms, `b` is "above" `a` in the lattice. At the top of the lattice is the single ancestor of all values, called [top](#top), denoted `_` in CUE. Every value is an instance of top. At the bottom of the lattice is the value called [bottom](#bottom), denoted `_|_`. A bottom value usually indicates an error. Bottom is an instance of every value. An _atom_ is any value whose only instances are itself and bottom. Examples of atoms are `42.0`, `"hello"`, `true`, and `null`. A value is _concrete_ if it is either an atom, or a struct whose field values are all concrete, recursively. CUE's values also include what we normally think of as types, like `string` and `float`. It does not distinguish between types and values: only the relationship of values in the lattice is important. Each CUE "type" subsumes the concrete values that one would normally think of as part of that type. For example, `"hello"` is an instance of `string`, and `42.0` is an instance of `float`. In addition to `string` and `float`, CUE has `null`, `int`, `bool`, and `bytes`. We informally call these CUE's "basic types". ``` false ⊑ bool true ⊑ bool true ⊑ true 5.0 ⊑ float bool ⊑ _ _|_ ⊑ _ _|_ ⊑ _|_ _ ⋢ _|_ _ ⋢ bool int ⋢ bool bool ⋢ int false ⋢ true true ⋢ false float ⋢ 5.0 5 ⋢ 6 ``` ### Unification The _unification_ of values `a` and `b` is defined as the greatest lower bound of `a` and `b`. (That is, the value `u` such that `u ⊑ a` and `u ⊑ b`, and for any other value `v` for which `v ⊑ a` and `v ⊑ b` it holds that `v ⊑ u`.) Since CUE values form a lattice, the unification of two CUE values is always unique. These all follow from the definition of unification: - The unification of `a` with itself is always `a`. - The unification of values `a` and `b` where `a ⊑ b` is always `a`. - The unification of a value with bottom is always bottom. Unification in CUE is a [binary expression](#operands), written `a & b`. It is commutative, associative, and idempotent. As a consequence, order of evaluation is irrelevant, a property that is key to many of the constructs in the CUE language as well as the tooling layered on top of it. ### Disjunction The _disjunction_ of values `a` and `b` is defined as the least upper bound of `a` and `b`. (That is, the value `d` such that `a ⊑ d` and `b ⊑ d`, and for any other value `e` for which `a ⊑ e` and `b ⊑ e`, it holds that `d ⊑ e`.) This style of disjunctions is sometimes also referred to as sum types. Since CUE values form a lattice, the disjunction of two CUE values is always unique. These all follow from the definition of disjunction: - The disjunction of `a` with itself is always `a`. - The disjunction of a value `a` and `b` where `a ⊑ b` is always `b`. - The disjunction of a value `a` with bottom is always `a`. - The disjunction of two bottom values is bottom. Disjunction in CUE is a [binary expression](#operands), written `a | b`. It is commutative, associative, and idempotent. The unification of a disjunction with another value is equal to the disjunction composed of the unification of this value with all of the original elements of the disjunction. In other words, unification distributes over disjunction. ``` (a_0 | ... |a_n) & b ==> a_0&b | ... | a_n&b. ``` ``` Expression Result ({a:1} | {b:2}) & {c:3} {a:1, c:3} | {b:2, c:3} (int | string) & "foo" "foo" ("a" | "b") & "c" _|_ ``` A disjunction is _normalized_ if there is no element `a` for which there is an element `b` such that `a ⊑ b`. #### Default values Any value `v` _may_ be associated with a default value `d`, where `d` must be in instance of `v` (`d ⊑ v`). Default values are introduced by means of disjunctions. Any element of a disjunction can be _marked_ as a default by prefixing it with an asterisk `*` ([a unary expression](#operators)). Syntactically consecutive disjunctions are considered to be part of a single disjunction, whereby multiple disjuncts can be marked as default. A _marked disjunction_ is one where any of its terms are marked. So `a | b | *c | d` is a single marked disjunction of four terms, whereas `a | (b | *c | d)` is an unmarked disjunction of two terms, one of which is a marked disjunction of three terms. During unification, if all the marked disjuncts of a marked disjunction are eliminated, then the remaining unmarked disjuncts are considered as if they originated from an unmarked disjunction As explained below, distinguishing the nesting of disjunctions like this is only relevant when both an outer and nested disjunction are marked. Intuitively, when an expression needs to be resolved for an operation other than unification or disjunction, non-starred elements are dropped in favor of starred ones if the starred ones do not resolve to bottom. To define the unification and disjunction operation we use the notation `⟨v⟩` to denote a CUE value `v` that is not associated with a default and the notation `⟨v, d⟩` to denote a value `v` associated with a default value `d`. The rewrite rules for unifying such values are as follows: ``` U0: ⟨v1⟩ & ⟨v2⟩ => ⟨v1&v2⟩ U1: ⟨v1, d1⟩ & ⟨v2⟩ => ⟨v1&v2, d1&v2⟩ U2: ⟨v1, d1⟩ & ⟨v2, d2⟩ => ⟨v1&v2, d1&d2⟩ ``` The rewrite rules for disjoining terms of unmarked disjunctions are ``` D0: ⟨v1⟩ | ⟨v2⟩ => ⟨v1|v2⟩ D1: ⟨v1, d1⟩ | ⟨v2⟩ => ⟨v1|v2, d1⟩ D2: ⟨v1, d1⟩ | ⟨v2, d2⟩ => ⟨v1|v2, d1|d2⟩ ``` Terms of marked disjunctions are first rewritten according to the following rules: ``` M0: ⟨v⟩ => ⟨v⟩ don't introduce defaults for unmarked term M1: *⟨v⟩ => ⟨v, v⟩ introduce identical default for marked term M2: *⟨v, d⟩ => ⟨v, d⟩ keep existing defaults for marked term M3: ⟨v, d⟩ => ⟨v⟩ strip existing defaults from unmarked term ``` Note that for any marked disjunction `a`, the expressions `a|a`, `*a|a` and `*a|*a` all resolve to `a`. ``` Expression Value-default pair Rules applied *"tcp" | "udp" ⟨"tcp"|"udp", "tcp"⟩ M1, D1 string | *"foo" ⟨string, "foo"⟩ M1, D1 *1 | 2 | 3 ⟨1|2|3, 1⟩ M1, D1 (*1|2|3) | (1|*2|3) ⟨1|2|3, 1|2⟩ M1, D1, D2 (*1|2|3) | *(1|*2|3) ⟨1|2|3, 2⟩ M1, M2, M3, D1, D2 (*1|2|3) | (1|*2|3)&2 ⟨1|2|3, 1|2⟩ M1, D1, U1, D2 (*1|2) & (1|*2) ⟨1|2, _|_⟩ M1, D1, U2 ``` The rules of subsumption for defaults can be derived from the above definitions and are as follows. ``` ⟨v2, d2⟩ ⊑ ⟨v1, d1⟩ if v2 ⊑ v1 and d2 ⊑ d1 ⟨v1, d1⟩ ⊑ ⟨v⟩ if v1 ⊑ v ⟨v⟩ ⊑ ⟨v1, d1⟩ if v ⊑ d1 ``` ``` Expression Resolves to "tcp" | "udp" "tcp" | "udp" *"tcp" | "udp" "tcp" float | *1 1 *string | 1.0 string (*1|2) + (2|*3) 4 (*1|2|3) | (1|*2|3) 1|2 (*1|2|3) & (1|*2|3) 1|2|3 // default is _|_ (* >=5 | int) & (* <=5 | int) 5 (*"tcp"|"udp") & ("udp"|*"tcp") "tcp" (*"tcp"|"udp") & ("udp"|"tcp") "tcp" (*"tcp"|"udp") & "tcp" "tcp" (*"tcp"|"udp") & (*"udp"|"tcp") "tcp" | "udp" // default is _|_ (*true | false) & bool true (*true | false) & (true | false) true {a: 1} | {b: 1} {a: 1} | {b: 1} {a: 1} | *{b: 1} {b:1} *{a: 1} | *{b: 1} {a: 1} | {b: 1} ({a: 1} | {b: 1}) & {a:1} {a:1} | {a: 1, b: 1} ({a:1}|*{b:1}) & ({a:1}|*{b:1}) {b:1} ``` ### Bottom and errors Any evaluation error in CUE results in a bottom value, represented by the token `_|_`. Bottom is an instance of every other value. Any evaluation error is represented as bottom. Implementations may associate error strings with different instances of bottom; logically they all remain the same value. ``` bottom_lit = "_|_" . ``` ### Top Top is represented by the underscore character `_`, lexically an identifier. Unifying any value `v` with top results in `v` itself. ``` Expr Result _ & 5 5 _ & _ _ _ & _|_ _|_ _ | _|_ _ ``` ### Null The _null value_ is represented with the keyword `null`. It has only one parent, top, and one child, bottom. It is unordered with respect to any other value. ``` null_lit = "null" . ``` ``` null & 8 _|_ null & _ null null & _|_ _|_ ``` ### Boolean values A _boolean type_ represents the set of Boolean truth values denoted by the keywords `true` and `false`. The predeclared boolean type is `bool`; it is a defined type and a separate element in the lattice. ``` bool_lit = "true" | "false" . ``` ``` bool & true true true & true true true & false _|_ bool & (false|true) false | true bool & (true|false) true | false ``` ### Numeric values The _integer type_ represents the set of all integral numbers. The _decimal floating-point type_ represents the set of all decimal floating-point numbers. They are two distinct types. Both are instances instances of a generic `number` type. The predeclared number, integer, and decimal floating-point types are `number`, `int` and `float`; they are defined types. A decimal floating-point literal always has type `float`; it is not an instance of `int` even if it is an integral number. Integer literals are always of type `int` and don't match type `float`. Numeric literals are exact values of arbitrary precision. If the operation permits it, numbers should be kept in arbitrary precision. Implementation restriction: although numeric values have arbitrary precision in the language, implementations may implement them using an internal representation with limited precision. That said, every implementation must: - Represent integer values with at least 256 bits. - Represent floating-point values with a mantissa of at least 256 bits and a signed binary exponent of at least 16 bits. - Give an error if unable to represent an integer value precisely. - Give an error if unable to represent a floating-point value due to overflow. - Round to the nearest representable value if unable to represent a floating-point value due to limits on precision. These requirements apply to the result of any expression except for builtin functions, for which an unusual loss of precision must be explicitly documented. ### Strings The _string type_ represents the set of UTF-8 strings, not allowing surrogates. The predeclared string type is `string`; it is a defined type. The length of a string `s` (its size in bytes) can be discovered using the builtin function `len`. ### Bytes The _bytes type_ represents the set of byte sequences. A byte sequence value is a (possibly empty) sequence of bytes. The number of bytes is called the length of the byte sequence and is never negative. The predeclared byte sequence type is `bytes`; it is a defined type. ### Bounds A _bound_, syntactically a [unary expression](#operands), defines a logically infinite disjunction of concrete values represented as a single comparison. For example, `>= 2` represents the infinite disjunction `2|3|4|5|6|7|…`. For any [comparison operator](#comparison-operators) `op` except `==`, `op a` is the disjunction of every `x` such that `x op a`. ``` 2 & >=2 & <=5 // 2, where 2 is either an int or float. 2.5 & >=1 & <=5 // 2.5 2 & >=1.0 & <3.0 // 2.0 2 & >1 & <3.0 // 2.0 2.5 & int & >1 & <5 // _|_ 2.5 & float & >1 & <5 // 2.5 int & 2 & >1.0 & <3.0 // _|_ 2.5 & >=(int & 1) & <5 // _|_ >=0 & <=7 & >=3 & <=10 // >=3 & <=7 !=null & 1 // 1 >=5 & <=5 // 5 ``` ### Structs A _struct_ is a set of elements called _fields_, each of which has a name, called a _label_, and value. We say a label is _defined_ for a struct if the struct has a field with the corresponding label. The value for a label `f` of struct `a` is denoted `a.f`. A struct `a` is an instance of `b`, or `a ⊑ b`, if for any label `f` defined for `b`, label `f` is also defined for `a` and `a.f ⊑ b.f`. Note that if `a` is an instance of `b` it may have fields with labels that are not defined for `b`. The (unique) struct with no fields, written `{}`, has every struct as an instance. It can be considered the type of all structs. ``` {a: 1} ⊑ {} {a: 1, b: 1} ⊑ {a: 1} {a: 1} ⊑ {a: int} {a: 1, b: 1.0} ⊑ {a: int, b: number} {} ⋢ {a: 1} {a: 2} ⋢ {a: 1} {a: 1} ⋢ {b: 1} ``` The successful unification of structs `a` and `b` is a new struct `c` which has all fields of both `a` and `b`, where the value of a field `f` in `c` is `a.f & b.f` if `f` is defined in both `a` and `b`, or just `a.f` or `b.f` if `f` is in just `a` or `b`, respectively. Any [references](#references) to `a` or `b` in their respective field values need to be replaced with references to `c`. The result of a unification is bottom (`_|_`) if any of its defined fields evaluates to bottom, recursively. A struct literal may contain multiple fields with the same label, the result of which is the unification of all those fields. ``` StructLit = "{" { Declaration "," } "}" . Declaration = Field | Ellipsis | Embedding | LetClause | attribute . Ellipsis = "..." [ Expression ] . Embedding = Comprehension | AliasExpr . Field = Label ":" { Label ":" } AliasExpr { attribute } . Label = [ identifier "=" ] LabelExpr . LabelExpr = LabelName [ "?" | "!" ] | "[" AliasExpr "]" . LabelName = identifier | simple_string_lit | "(" AliasExpr ")" . attribute = "@" identifier "(" attr_tokens ")" . attr_tokens = { attr_token | "(" attr_tokens ")" | "[" attr_tokens "]" | "{" attr_tokens "}" } . attr_token = /* any token except '(', ')', '[', ']', '{', or '}' */ ``` ``` Expression Result {a: int, a: 1} {a: 1} {a: int} & {a: 1} {a: 1} {a: >=1 & <=7} & {a: >=5 & <=9} {a: >=5 & <=7} {a: >=1 & <=7, a: >=5 & <=9} {a: >=5 & <=7} {a: 1} & {b: 2} {a: 1, b: 2} {a: 1, b: int} & {b: 2} {a: 1, b: 2} {a: 1} & {a: 2} _|_ ``` #### Field constraints A struct may declare _field constraints_ which define values that should be unified with a given field once it is defined. The existence of a field constraint declares, but does not define, that field. Syntactically, a field is marked as a constraint by following its label with an _optional_ marker `?` or _required_ marker `!`. These markers are not part of the field name. A struct that has a required field constraint with a bottom value evaluates to bottom. An optional field constraint with a bottom value does _not_ invalidate the struct that contains it as long as it is not unified with a defined field. The subsumption relation for fields with the various markers is defined as ``` {a: x} ⊑ {a!: x} ⊑ {a?: x} ``` for any given `x`. Implementations may error upon encountering a required field constraint when manifesting CUE as data. ``` Expression Result {foo?: 3} & {foo: 3} {foo: 3} {foo!: 3} & {foo: 3} {foo: 3} {foo!: int} & {foo: int} {foo: int} {foo!: int} & {foo?: <1} {foo!: <1} {foo!: int} & {foo: <=3} {foo: <=3} {foo!: int} & {foo: 3} {foo: 3} {foo!: 3} & {foo: int} {foo: 3} {foo!: 3} & {foo: <=4} {foo: 3} {foo?: 1} & {foo?: 2} {foo?: _|_} // No error {foo?: 1} & {foo!: 2} _|_ {foo?: 1} & {foo: 2} _|_ ``` #### Dynamic fields A _dynamic field_ is a field whose label is determined by an expression wrapped in parentheses. A dynamic field may be marked as optional or required. ``` Expression Result a: "foo" a: "foo" b: "bar" b: "bar" (a): "baz" foo: "baz" (a+b): "qux" foobar: "qux" (a)?: string foo?: string (b)!: string bar!: string ``` #### Pattern and default constraints A struct may define constraints that apply to a collection of fields. A _pattern constraint_, denoted `[pattern]: value`, defines a pattern, which is a value of type string, and a value to unify with fields whose label unifies with the pattern. For a given struct `a` with pattern constraint `[p]: v`, `v` is unified with any field with name `f` in `a` for which `p & f` is not bottom. When unifying struct `a` and `b`, any pattern constraint declared in `a` and `b` are also declared in the result of unification. Additionally, a _default constraint_, denoted `...value`, defines a value to unify with any field for which there is no other declaration in a struct. When unifying structs `a` and `b`, a default constraint `...v` declared in `a` defines that the value `v` should unify with any field in the resulting struct `c` whose label does not unify with any of the patterns of the pattern constraints defined for `a` _and_ for which there exists no field declaration in `a` with that label. The token `...` is a shorthand for `..._`. _Note_: default constraints of the form `..._` are not yet implemented. ``` a: { foo: string // foo is a string [=~"^i"]: int // all other fields starting with i are integers [=~"^b"]: bool // all other fields starting with b are booleans [>"c"]: string // all other fields lexically after c are strings ...string // all other fields must be a string. Note: default constraints are not yet implemented. } b: a & { i3: 3 bar: true other: "a string" } ``` Concrete field labels may be an identifier or string, the latter of which may be interpolated. Fields with identifier labels can be referred to within the scope they are defined, string labels cannot. References within such interpolated strings are resolved within the scope of the struct in which the label sequence is defined and can reference concrete labels lexically preceding the label within a label sequence. ``` intMap: [string]: int intMap: { t1: 43 t2: 2.4 // error: 2.4 is not an integer } nameMap: [string]: { firstName: string nickName: *firstName | string } nameMap: hank: firstName: "Hank" ``` The optional field set defined by `nameMap` matches every field, in this case just `hank`, and unifies the associated constraint with the matched field, resulting in: ``` nameMap: hank: { firstName: "Hank" nickName: "Hank" } ``` #### Closed structs By default, structs are open to adding fields. Instances of an open struct `p` may contain fields not defined in `p`. This is makes it easy to add fields, but can lead to bugs: ``` S: { field1: string } S1: S & { field2: "foo" } // S1 is { field1: string, field2: "foo" } A: { field1: string field2: string } A1: A & { feild1: "foo" // "field1" was accidentally misspelled } // A1 is // { field1: string, field2: string, feild1: "foo" } // not the intended // { field1: "foo", field2: string } ``` A _closed struct_ `c` is a struct whose instances may not declare any field with a name that does not match the name of a field or the pattern of a pattern constraint defined in `c`. Hidden fields are excluded from this limitation. A struct that is the result of unifying any struct with a [`...`](#structs) declaration is defined for all regular fields. Closing a struct is equivalent to adding `..._|_` to it. Syntactically, structs are closed explicitly with the `close` builtin or implicitly and recursively by [definitions](#definitions-and-hidden-fields). ``` A: close({ field1: string field2: string }) A1: A & { feild1: string } // _|_ feild1 not defined for A A2: A & { for k,v in { feild1: string } { k: v } } // _|_ feild1 not defined for A C: close({ [_]: _ }) C2: C & { for k,v in { thisIsFine: string } { "\(k)": v } } D: close({ // Values generated by comprehensions are treated as embeddings. for k,v in { x: string } { "\(k)": v } }) ``` #### Embedding A struct may contain an _embedded value_, an operand used as a declaration. An embedded value of type struct is unified with the struct in which it is embedded, but disregarding the restrictions imposed by closed structs. So if an embedding resolves to a closed struct, the corresponding enclosing struct will also be closed, but may have fields that are not allowed if normal rules for closed structs were observed. If an embedded value is not of type struct, the struct may only have definitions or hidden fields. Regular fields are not allowed in such case. The result of `{ A }` is `A` for any `A` (including definitions). Syntactically, embeddings may be any expression. ``` S1: { a: 1 b: 2 { c: 3 } } // S1 is { a: 1, b: 2, c: 3 } S2: close({ a: 1 b: 2 { c: 3 } }) // same as close(S1) S3: { a: 1 b: 2 close({ c: 3 }) } // same as S2 ``` #### Definitions and hidden fields A field is a _definition_ if its identifier starts with `#` or `_#`. A field is _hidden_ if its identifier starts with a `_`. All other fields are _regular_. Definitions and hidden fields are not emitted when converting a CUE program to data and are never required to be concrete. Referencing a definition will recursively [close](#closed-structs) it. That is, a referenced definition will not unify with a struct that would add a field anywhere within the definition that it does not already define or explicitly allow with a pattern constraint or `...`. [Embedding](#embedding) allows bypassing this check. If referencing a definition would always result in an error, implementations may report this inconsistency at the point of its declaration. ``` #MyStruct: { sub: field: string } #MyStruct: { sub: enabled?: bool } myValue: #MyStruct & { sub: feild: 2 // error, feild not defined in #MyStruct sub: enabled: true // okay } #D: { #OneOf c: int // adds this field. } #OneOf: { a: int } | { b: int } D1: #D & { a: 12, c: 22 } // { a: 12, c: 22 } D2: #D & { a: 12, b: 33 } // _|_ // cannot define both `a` and `b` ``` ``` #A: {a: int} B: { #A b: c: int } x: B x: d: 3 // not allowed, as closed by embedded #A y: B.b y: d: 3 // allowed as nothing closes b #B: { #A b: c: int } z: #B.b z: d: 3 // not allowed, as referencing #B closes b ``` #### Attributes Attributes allow associating meta information with values. Their primary purpose is to define mappings between CUE and other representations. Attributes do not influence the evaluation of CUE. An attribute associates an identifier with a value, a balanced token sequence, which is a sequence of CUE tokens with balanced brackets (`()`, `[]`, and `{}`). The sequence may not contain interpolations. Fields, structs and packages can be associated with a set of attributes. Attributes accumulate during unification, but implementations may remove duplicates that have the same source string representation. The interpretation of an attribute, including the handling of multiple attributes for a given identifier, is up to the consumer of the attribute. Field attributes define additional information about a field, such as a mapping to a protocol buffer tag or alternative name of the field when mapping to a different language. ``` // Package attribute @protobuf(proto3) myStruct1: { // Struct attribute: @jsonschema(id="https://example.org/mystruct1.json") // Field attributes field: string @go(Field) attr: int @xml(,attr) @go(Attr) } myStruct2: { field: string @go(Field) attr: int @xml(a1,attr) @go(Attr) } Combined: myStruct1 & myStruct2 // field: string @go(Field) // attr: int @xml(,attr) @xml(a1,attr) @go(Attr) ``` #### Aliases Aliases name values that can be referred to within the [scope](#declarations-and-scopes) in which they are declared. The name of an alias must be unique within its scope. ``` AliasExpr = [ identifier "=" ] Expression . ``` Aliases can appear in several positions: In front of a Label (`X=label: value`): - binds the identifier to the same value as `label` would be bound to if it were a valid identifier. In front of a dynamic field (`X=(label): value`): - binds the identifier to the same value as `label` if it were a valid static identifier. In front of a dynamic field expression (`(X=expr): value`): - binds the identifier to the concrete label resulting from evaluating `expr`. In front of a pattern constraint (`X=[expr]: value`): - binds the identifier to the same field as the matched by the pattern within the instance of the field value (`value`). In front of a pattern constraint expression (`[X=expr]: value`): - binds the identifier to the concrete label that matches `expr` within the instances of the field value (`value`). Before a value (`foo: X=x`) - binds the identifier to the value it precedes within the scope of that value. Before a list element (`[ X=value, X+1 ]`) (Not yet implemented) - binds the identifier to the list element it precedes within the scope of the list expression. ``` // A field alias foo: X // 4 X="not an identifier": 4 // A value alias foo: X={x: X.a} bar: foo & {a: 1} // {a: 1, x: 1} // A label alias [Y=string]: { name: Y } foo: { value: 1 } // outputs: foo: { name: "foo", value: 1 } ``` #### Let declarations _Let declarations_ bind an identifier to an expression. The identifier is only visible within the [scope](#declarations-and-scopes) in which it is declared. The identifier must be unique within its scope. ``` let x = expr a: x + 1 b: x + 2 ``` #### Shorthand notation for nested structs A field whose value is a struct with a single field may be written as a colon-separated sequence of the two field names, followed by a colon and the value of that single field. ``` job: myTask: replicas: 2 ``` expands to ``` job: { myTask: { replicas: 2 } } ``` ### Lists A list literal defines a new value of type list. A list may be open or closed. An open list is indicated with a `...` at the end of an element list, optionally followed by a value for the remaining elements. The length of a closed list is the number of elements it contains. The length of an open list is the number of elements as a lower bound and an unlimited number of elements as its upper bound. ``` ListLit = "[" [ ElementList [ "," ] ] "]" . ElementList = Ellipsis | Embedding { "," Embedding } [ "," Ellipsis ] . ``` Lists can be thought of as structs: ``` List: *null | { Elem: _ Tail: List } ``` For closed lists, `Tail` is `null` for the last element, for open lists it is `*null | List`, defaulting to the shortest variant. For instance, the open list [ 1, 2, ... ] can be represented as: ``` open: List & { Elem: 1, Tail: { Elem: 2 } } ``` and the closed version of this list, [ 1, 2 ], as ``` closed: List & { Elem: 1, Tail: { Elem: 2, Tail: null } } ``` Using this representation, the subsumption rule for lists can be derived from those of structs. Implementations are not required to implement lists as structs. The `Elem` and `Tail` fields are not special and `len` will not work as expected in these cases. ## Declarations and Scopes ### Blocks A _block_ is a possibly empty sequence of declarations. The braces of a struct literal `{ ... }` form a block, but there are others as well: - The _universe block_ encompasses all CUE source text. - Each [package](#modules-instances-and-packages) has a _package block_ containing all CUE source text in that package. - Each file has a _file block_ containing all CUE source text in that file. - Each `for` and `let` clause in a [comprehension](#comprehensions) is considered to be its own implicit block. Blocks nest and influence scoping. ### Declarations and scope A _declaration_ may bind an identifier to a field, alias, or package. Every identifier in a program must be declared. Other than for fields, no identifier may be declared twice within the same block. For fields, an identifier may be declared more than once within the same block, resulting in a field with a value that is the result of unifying the values of all fields with the same identifier. String labels do not bind an identifier to the respective field. The _scope_ of a declared identifier is the extent of source text in which the identifier denotes the specified field, alias, or package. CUE is lexically scoped using blocks: 1. The scope of a [predeclared identifier](#predeclared-identifiers) is the universe block. 1. The scope of an identifier denoting a field declared at top level (outside any struct literal) is the package block. 1. The scope of an identifier denoting an alias declared at top level (outside any struct literal) is the file block. 1. The scope of a let identifier declared at top level (outside any struct literal) is the file block. 1. The scope of the package name of an imported package is the file block of the file containing the import declaration. 1. The scope of a field, alias or let identifier declared inside a struct literal is the innermost containing block. An identifier declared in a block may be redeclared in an inner block. While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration. The package clause is not a declaration; the package name does not appear in any scope. Its purpose is to identify the files belonging to the same package and to specify the default name for import declarations. ### Predeclared identifiers CUE predefines a set of types and builtin functions. For each of these there is a corresponding keyword which is the name of the predefined identifier, prefixed with `__`. ``` Functions len close and or Types null The null type and value bool All boolean values int All integral numbers float All decimal floating-point numbers string Any valid UTF-8 sequence bytes Any valid byte sequence Derived Value number int | float uint >=0 uint8 >=0 & <=255 int8 >=-128 & <=127 uint16 >=0 & <=65535 int16 >=-32_768 & <=32_767 rune >=0 & <=0x10FFFF uint32 >=0 & <=4_294_967_295 int32 >=-2_147_483_648 & <=2_147_483_647 uint64 >=0 & <=18_446_744_073_709_551_615 int64 >=-9_223_372_036_854_775_808 & <=9_223_372_036_854_775_807 uint128 >=0 & <=340_282_366_920_938_463_463_374_607_431_768_211_455 int128 >=-170_141_183_460_469_231_731_687_303_715_884_105_728 & <=170_141_183_460_469_231_731_687_303_715_884_105_727 float32 >=-3.40282346638528859811704183484516925440e+38 & <=3.40282346638528859811704183484516925440e+38 float64 >=-1.797693134862315708145274237317043567981e+308 & <=1.797693134862315708145274237317043567981e+308 ``` ### Exported identifiers An identifier of a package may be exported to permit access to it from another package. All identifiers not starting with `_` (so all regular fields and definitions starting with `#`) are exported. Any identifier starting with `_` is not visible outside the package and resides in a separate namespace than namesake identifiers of other packages. ``` package mypackage foo: string // visible outside mypackage "bar": string // visible outside mypackage #Foo: { // visible outside mypackage a: 1 // visible outside mypackage _b: 2 // not visible outside mypackage #C: { // visible outside mypackage d: 4 // visible outside mypackage } _#E: foo // not visible outside mypackage } ``` ### Uniqueness of identifiers Given a set of identifiers, an identifier is called unique if it is different from every other in the set, after applying normalization following [Unicode Annex #31](https://unicode.org/reports/tr31/). Two identifiers are different if they are spelled differently or if they appear in different packages and are not exported. Otherwise, they are the same. ### Field declarations A field associates the value of an expression to a label within a struct. If this label is an identifier, it binds the field to that identifier, so the field's value can be referenced by writing the identifier. String labels are not bound to fields. ``` a: { b: 2 "s": 3 c: b // 2 d: s // _|_ unresolved identifier "s" e: a.s // 3 } ``` If an expression may result in a value associated with a default value as described in [default values](#default-values), the field binds to this value-default pair. ### Let declarations Within a struct, a let clause binds an identifier to the given expression. Within the scope of the identifier, the identifier refers to the _locally declared_ expression. The expression is evaluated in the scope it was declared. ## Expressions An expression specifies the computation of a value by applying operators and builtin functions to operands. Expressions that require concrete values are called _incomplete_ if any of their operands are not concrete, but define a value that would be legal for that expression. Incomplete expressions may be left unevaluated until a concrete value is requested at the application level. ### Operands Operands denote the elementary values in an expression. An operand may be a literal, a (possibly qualified) identifier denoting a field, alias, or let declaration, or a parenthesized expression. ``` Operand = Literal | OperandName | "(" Expression ")" . Literal = BasicLit | ListLit | StructLit . BasicLit = int_lit | float_lit | string_lit | null_lit | bool_lit | bottom_lit . OperandName = identifier | QualifiedIdent . ``` ### Qualified identifiers A qualified identifier is an identifier qualified with a package name prefix. ``` QualifiedIdent = PackageName "." identifier . ``` A qualified identifier accesses an identifier in a different package, which must be [imported](#import-declarations). The identifier must be declared in the [package block](#blocks) of that package. ``` math.Sin // denotes the Sin function in package math ``` ### References An identifier operand refers to a field and is called a reference. The value of a reference is a copy of the expression associated with the field that it is bound to, with any references within that expression bound to the respective copies of the fields they were originally bound to. Implementations may use a different mechanism to evaluate as long as these semantics are maintained. ``` a: { place: string greeting: "Hello, \(place)!" } b: a & { place: "world" } c: a & { place: "you" } d: b.greeting // "Hello, world!" e: c.greeting // "Hello, you!" ``` ### Primary expressions Primary expressions are the operands for unary and binary expressions. ``` PrimaryExpr = Operand | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Arguments . Selector = "." (identifier | simple_string_lit) . Index = "[" Expression "]" . Argument = Expression . Arguments = "(" [ ( Argument { "," Argument } ) [ "," ] ] ")" . ``` ``` x 2 (s + ".txt") f(3.1415, true) m["foo"] obj.color f.p[i].x ``` ### Selectors For a [primary expression](#primary-expressions) `x` that is not a [package name](#package-clause), the selector expression ``` x.f ``` denotes the element of a struct `x` identified by `f`. `f` must be an identifier or a string literal identifying any definition or regular non-optional field. The identifier `f` is called the field selector. If `x` is a package name, see the section on [qualified identifiers](#qualified-identifiers). Otherwise, if `x` is not a struct, or if `f` does not exist in `x`, the result of the expression is bottom (an error). In the latter case the expression is incomplete. The operand of a selector may be associated with a default. ``` T: { x: int y: 3 "x-y": 4 } a: T.x // int b: T.y // 3 c: T.z // _|_ // field 'z' not found in T d: T."x-y" // 4 e: {a: 1|*2} | *{a: 3|*4} f: e.a // 4 (default value) ``` ### Index expressions A primary expression of the form ``` a[x] ``` denotes the element of a list or struct `a` indexed by `x`. The value `x` is called the index or field name, respectively. The following rules apply: If `a` is not a struct: - `a` is a list (which need not be complete) - the index `x` unified with `int` must be concrete. - the index `x` is in range if `0 <= x < len(a)`, where only the explicitly defined values of an open-ended list are considered, otherwise it is out of range The result of `a[x]` is for `a` of list type: - the list element at index `x`, if `x` is within range - bottom (an error), otherwise for `a` of struct type: - the index `x` unified with `string` must be concrete. - the value of the regular and non-optional field named `x` of struct `a`, if this field exists - bottom (an error), otherwise ``` a: [ 1, 2 ][1] // 2 b: [ 1, 2 ][2] // _|_ c: [ 1, 2, ...][2] // _|_ // Defaults are selected for both operand and index: x: [1, 2] | *[3, 4] y: int | *1 z: x[y] // 4 ``` ### Operators Operators combine operands into expressions. ``` Expression = UnaryExpr | Expression binary_op Expression . UnaryExpr = PrimaryExpr | unary_op UnaryExpr . binary_op = "|" | "&" | "||" | "&&" | "==" | rel_op | add_op | mul_op . rel_op = "!=" | "<" | "<=" | ">" | ">=" | "=~" | "!~" . add_op = "+" | "-" . mul_op = "*" | "/" . unary_op = "+" | "-" | "!" | "*" | rel_op . ``` Comparisons are discussed [elsewhere](#comparison-operators). For any binary operators, the operand types must unify. #### Operator precedence Unary operators have the highest precedence. There are eight precedence levels for binary operators. Multiplication operators binds strongest, followed by addition operators, comparison operators, `&&` (logical AND), `||` (logical OR), `&` (unification), and finally `|` (disjunction): ``` Precedence Operator 7 * / 6 + - 5 == != < <= > >= =~ !~ 4 && 3 || 2 & 1 | ``` Binary operators of the same precedence associate from left to right. For instance, `x / y * z` is the same as `(x / y) * z`. ``` +x 23 + 3*x[i] x <= f() f() || g() x == y+1 && y == z-1 2 | int { a: 1 } & { b: 2 } ``` #### Arithmetic operators Arithmetic operators apply to numeric values and yield a result of the same type as the first operand. The four standard arithmetic operators `(+, -, *, /)` apply to integer and decimal floating-point types; `+` and `*` also apply to strings and bytes. ``` + sum integers, floats, strings, bytes - difference integers, floats * product integers, floats, strings, bytes / quotient integers, floats ``` For any operator that accepts operands of type `float`, any operand may be of type `int` or `float`, in which case the result will be `float` if it cannot be represented as an `int` or if any of the operands are `float`, or `int` otherwise. So the result of `1 / 2` is `0.5` and is of type `float`. The result of division by zero is bottom (an error). Integer division is implemented through the builtin functions `quo`, `rem`, `div`, and `mod`. The unary operators `+` and `-` are defined for numeric values as follows: ``` +x is 0 + x -x negation is 0 - x ``` #### String operators Strings can be concatenated using the `+` operator: ``` s: "hi " + name + " and good bye" ``` String addition creates a new string by concatenating the operands. A string can be repeated by multiplying it: ``` s: "etc. "*3 // "etc. etc. etc. " ``` ##### Comparison operators Comparison operators compare two operands and yield an untyped boolean value. ``` == equal != not equal < less <= less or equal > greater >= greater or equal =~ matches regular expression !~ does not match regular expression ``` In any comparison, the types of the two operands must unify or one of the operands must be null. The equality operators `==` and `!=` apply to operands that are comparable. The ordering operators `<`, `<=`, `>`, and `>=` apply to operands that are ordered. The matching operators `=~` and `!~` apply to a string and a regular expression operand. These terms and the result of the comparisons are defined as follows: - Null is comparable with itself and any other type. Two null values are always equal, null is unequal with anything else. - Boolean values are comparable. Two boolean values are equal if they are either both true or both false. - Integer values are comparable and ordered, in the usual way. - Floating-point values are comparable and ordered, as per the definitions for binary coded decimals in the IEEE-754-2008 standard. - Floating point numbers may be compared with integers. - String and bytes values are comparable and ordered lexically byte-wise. - Struct are not comparable. - Lists are not comparable. - The regular expression syntax is the one accepted by RE2, described in https://github.com/google/re2/wiki/Syntax, except for `\C`. - `s =~ r` is true if `s` matches the regular expression `r`. - `s !~ r` is true if `s` does not match regular expression `r`. ``` 3 < 4 // true 3 < 4.0 // true null == 2 // false null != {} // true {} == {} // _|_: structs are not comparable against structs "Wild cats" =~ "cat" // true "Wild cats" !~ "dog" // true "foo" =~ "^[a-z]{3}$" // true "foo" =~ "^[a-z]{4}$" // false ``` #### Logical operators Logical operators apply to boolean values and yield a result of the same type as the operands. The right operand is evaluated conditionally. ``` && conditional AND p && q is "if p then q else false" || conditional OR p || q is "if p then true else q" ! NOT !p is "not p" ``` ### Calls Calls can be made to core library functions, called builtins. Given an expression `f` of function type F, ``` f(a1, a2, … an) ``` calls `f` with arguments `a1, a2, … an`. Arguments must be expressions of which the values are an instance of the parameter types of `F` and are evaluated before the function is called. ``` a: math.Atan2(x, y) ``` In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. The return parameters of the function are passed by value back to the calling function when the function returns. ### Comprehensions Lists and fields can be constructed using comprehensions. Comprehensions define a clause sequence that consists of a sequence of `for`, `if`, and `let` clauses, nesting from left to right. The sequence must start with a `for` or `if` clause. The `for` and `let` clauses each define a new scope in which new values are bound to be available for the next clause. The `for` clause binds the defined identifiers, on each iteration, to the next value of some iterable value in a new scope. A `for` clause may bind one or two identifiers. If there is one identifier, it binds it to the value of a list element or struct field value. If there are two identifiers, the first value will be the key or index, if available, and the second will be the value. For lists, `for` iterates over all elements in the list after closing it. For structs, `for` iterates over all non-optional regular fields. An `if` clause, or guard, specifies an expression that terminates the current iteration if it evaluates to false. The `let` clause binds the result of an expression to the defined identifier in a new scope. A current iteration is said to complete if the innermost block of the clause sequence is reached. Syntactically, the comprehension value is a struct. A comprehension can generate non-struct values by embedding such values within this struct. Within lists, the values yielded by a comprehension are inserted in the list at the position of the comprehension. Within structs, the values yielded by a comprehension are embedded within the struct. Both structs and lists may contain multiple comprehensions. ``` Comprehension = Clauses StructLit . Clauses = StartClause { [ "," ] Clause } . StartClause = ForClause | GuardClause . Clause = StartClause | LetClause . ForClause = "for" identifier [ "," identifier ] "in" Expression . GuardClause = "if" Expression . LetClause = "let" identifier "=" Expression . ``` ``` a: [1, 2, 3, 4] b: [for x in a if x > 1 { x+1 }] // [3, 4, 5] c: { for x in a if x < 4 let y = 1 { "\(x)": x + y } } d: { "1": 2, "2": 3, "3": 4 } ``` ### String interpolation String interpolation allows constructing strings by replacing placeholder expressions with their string representation. String interpolation may be used in single- and double-quoted strings, as well as their multiline equivalent. A placeholder consists of `\(` followed by an expression and `)`. The expression is evaluated in the scope within which the string is defined. The result of the expression is substituted as follows: - string: as is - bool: the JSON representation of the bool - number: a JSON representation of the number that preserves the precision of the underlying binary coded decimal - bytes: as if substituted within single quotes or converted to valid UTF-8 replacing the maximal subpart of ill-formed subsequences with a single replacement character (W3C encoding standard) otherwise - list: illegal - struct: illegal ``` a: "World" b: "Hello \( a )!" // Hello World! ``` ## Builtin Functions Builtin functions are predeclared. They are called like any other function. ### `len` The builtin function `len` takes arguments of various types and returns a result of type int. ``` Argument type Result bytes length of byte sequence list list length, smallest length for an open list struct number of distinct data fields, excluding field constraints ``` ``` Expression Result len("Hellø") 6 len([1, 2, 3]) 3 len([1, 2, ...]) 2 ``` ### `close` The builtin function `close` converts a partially defined, or open, struct to a fully defined, or closed, struct. ### `and` The builtin function `and` takes a list and returns the result of applying the `&` operator to all elements in the list. It returns top for the empty list. ``` Expression: Result and([a, b]) a & b and([a]) a and([]) _ ``` ### `or` The builtin function `or` takes a list and returns the result of applying the `|` operator to all elements in the list. It returns bottom for the empty list. ``` Expression: Result or([a, b]) a | b or([a]) a or([]) _|_ ``` ### `div`, `mod`, `quo` and `rem` For two integer values `x` and `y`, the integer quotient `q = div(x, y)` and remainder `r = mod(x, y)` implement Euclidean division and satisfy the following relationship: ``` r = x - y*q with 0 <= r < |y| ``` where `|y|` denotes the absolute value of `y`. ``` x y div(x, y) mod(x, y) 5 3 1 2 -5 3 -2 1 5 -3 -1 2 -5 -3 2 1 ``` For two integer values `x` and `y`, the integer quotient `q = quo(x, y)` and remainder `r = rem(x, y)` implement truncated division and satisfy the following relationship: ``` x = q*y + r and |r| < |y| ``` with `quo(x, y)` truncated towards zero. ``` x y quo(x, y) rem(x, y) 5 3 1 2 -5 3 -1 -2 5 -3 -1 2 -5 -3 1 -2 ``` A zero divisor in either case results in bottom (an error). ## Cycles Implementations are required to interpret or reject cycles encountered during evaluation according to the rules in this section. ### Reference cycles A _reference cycle_ occurs if a field references itself, either directly or indirectly. ``` // x references itself x: x // indirect cycles b: c c: d d: b ``` Implementations should treat these as `_`. Two particular cases are discussed below. #### Expressions that unify an atom with an expression An expression of the form `a & e`, where `a` is an atom and `e` is an expression, always evaluates to `a` or bottom. As it does not matter how we fail, we can assume the result to be `a` and postpone validating `a == e` until after all references in `e` have been resolved. ``` // Config Evaluates to (requiring concrete values) x: { x: { a: b + 100 a: _|_ // cycle detected b: a - 100 b: _|_ // cycle detected } } y: x & { y: { a: 200 a: 200 // asserted that 200 == b + 100 b: 100 } } ``` #### Field values A field value of the form `r & v`, where `r` evaluates to a reference cycle and `v` is a concrete value, evaluates to `v`. Unification is idempotent and unifying a value with itself ad infinitum, which is what the cycle represents, results in this value. Implementations should detect cycles of this kind, ignore `r`, and take `v` as the result of unification. ``` Configuration Evaluated // c Cycles in nodes of type struct evaluate // ↙︎ ↖ to the fixed point of unifying their // a → b values ad infinitum. a: b & { x: 1 } // a: { x: 1, y: 2, z: 3 } b: c & { y: 2 } // b: { x: 1, y: 2, z: 3 } c: a & { z: 3 } // c: { x: 1, y: 2, z: 3 } // resolve a b & {x:1} // substitute b c & {y:2} & {x:1} // substitute c a & {z:3} & {y:2} & {x:1} // eliminate a (cycle) {z:3} & {y:2} & {x:1} // simplify {x:1,y:2,z:3} ``` This rule also applies to field values that are disjunctions of unification operations of the above form. ``` a: b&{x:1} | {y:1} // {x:1,y:3,z:2} | {y:1} b: {x:2} | c&{z:2} // {x:2} | {x:1,y:3,z:2} c: a&{y:3} | {z:3} // {x:1,y:3,z:2} | {z:3} // resolving a b&{x:1} | {y:1} // substitute b ({x:2} | c&{z:2})&{x:1} | {y:1} // simplify c&{z:2}&{x:1} | {y:1} // substitute c (a&{y:3} | {z:3})&{z:2}&{x:1} | {y:1} // simplify a&{y:3}&{z:2}&{x:1} | {y:1} // eliminate a (cycle) {y:3}&{z:2}&{x:1} | {y:1} // expand {x:1,y:3,z:2} | {y:1} ``` Note that all nodes that form a reference cycle to form a struct will evaluate to the same value. If a field value is a disjunction, any element that is part of a cycle will evaluate to this value. ### Structural cycles A structural cycle is when a node references one of its ancestor nodes. It is possible to construct a structural cycle by unifying two acyclic values: ``` // acyclic y: { f: h: g g: _ } // acyclic x: { f: _ g: f } // introduces structural cycle z: x & y ``` Implementations should be able to detect such structural cycles dynamically. A structural cycle can result in infinite structure or evaluation loops. ``` // infinite structure a: b: a // infinite evaluation f: { n: int out: n + (f & {n: 1}).out } ``` CUE must allow or disallow structural cycles under certain circumstances. If a node `a` references an ancestor node, we call it and any of its field values `a.f` _cyclic_. So if `a` is cyclic, all of its descendants are also regarded as cyclic. A given node `x`, whose value is composed of the conjuncts `c1 & ... & cn`, is valid if any of its conjuncts is not cyclic. ``` // Disallowed: a list of infinite length with all elements being 1. #List: { head: 1 tail: #List } // Disallowed: another infinite structure (a:{b:{d:{b:{d:{...}}}}}, ...). a: { b: c } c: { d: a } // #List defines a list of arbitrary length. Because the recursive reference // is part of a disjunction, this does not result in a structural cycle. #List: { head: _ tail: null | #List } // Usage of #List. The value of tail in the most deeply nested element will // be `null`: as the value of the disjunct referring to list is the only // conjunct, all conjuncts are cyclic and the value is invalid and so // eliminated from the disjunction. MyList: #List & { head: 1, tail: { head: 2 }} ``` ## Modules, instances, and packages CUE configurations are constructed combining _instances_. An instance, in turn, is constructed from one or more source files belonging to the same _package_ that together declare the data representation. Elements of this data representation may be exported and used in other instances. ### Source file organization Each source file consists of an optional package clause defining collection of files to which it belongs, followed by a possibly empty set of import declarations that declare packages whose contents it wishes to use, followed by a possibly empty set of declarations. Like with a struct, a source file may contain embeddings. Unlike with a struct, the embedded expressions may be any value. If the result of the unification of all embedded values is not a struct, it will be output instead of its enclosing file when exporting CUE to a data format ``` SourceFile = { attribute "," } [ PackageClause "," ] { ImportDecl "," } { Declaration "," } . ``` ``` "Hello \(#place)!" #place: "world" // Outputs "Hello world!" ``` ### Package clause A package clause is an optional clause that defines the package to which a source file the file belongs. ``` PackageClause = "package" PackageName . PackageName = identifier . ``` The PackageName must not be a definition identifier. If the PackageName is the blank identifier (`_`), it is treated the same as if there were no package clause. This can be useful to allow adding package level attributes or doc comments to a CUE file without a package name. ``` package math ``` ### Modules and instances A _module_ defines a tree of directories, rooted at the _module root_. All source files within a module with the same package name belong to the same package. A module may define multiple packages. An _instance_ of a package is any subset of files belonging to the same package. It is interpreted as the concatenation of these files. An implementation may impose conventions on the layout of package files to determine which files of a package belongs to an instance. For example, an instance may be defined as the subset of package files belonging to a directory and all its ancestors. ### Import declarations An import declaration states that the source file containing the declaration depends on definitions of the _imported_ package and enables access to exported identifiers of that package. The import names an identifier (PackageName) to be used for access and an ImportPath that specifies the package to be imported. ``` ImportDecl = "import" ( ImportSpec | "(" { ImportSpec "," } ")" ) . ImportSpec = [ PackageName ] ImportPath . ImportLocation = { unicode_value } . ImportPath = `"` ImportLocation [ ":" identifier ] `"` . ``` The PackageName is used in qualified identifiers to access exported identifiers of the package within the importing source file. It is declared in the file block. It defaults to the identifier specified in the package clause of the imported package, which must match either the last path component of ImportLocation or the identifier following it. The interpretation of the ImportPath is implementation-dependent but it is typically either the path of a builtin package or a fully qualifying location of a package within a source code repository. An ImportLocation must be a non-empty string using only characters belonging to Unicode's L, M, N, P, and S general categories (the Graphic characters without spaces) and may not include the characters ``!"#$%&'()*,:;<=>?[\\]^`{|}`` or the Unicode replacement character U+FFFD. Assume we have package containing the package clause `package math`, which exports function `Sin` at the path identified by `lib/math`. This table illustrates how `Sin` is accessed in files that import the package after the various types of import declaration. ``` Import declaration Local name of Sin import "lib/math" math.Sin import "lib/math:math" math.Sin import m "lib/math" m.Sin ``` An import declaration declares a dependency relation between the importing and imported package. It is illegal for a package to import itself, directly or indirectly, or to directly import a package without referring to any of its exported identifiers. ### An example package TODO cue-lang-cue-db9cc73/doc/tutorial/000077500000000000000000000000001474664451600171105ustar00rootroot00000000000000cue-lang-cue-db9cc73/doc/tutorial/basics/000077500000000000000000000000001474664451600203545ustar00rootroot00000000000000cue-lang-cue-db9cc73/doc/tutorial/basics/README.md000066400000000000000000000002601474664451600216310ustar00rootroot00000000000000# CUE Tour The CUE Tour has now moved to https://cuelang.org/docs/tour/ with the source available under https://github.com/cue-lang/cuelang.org/tree/master/content/docs/tour. cue-lang-cue-db9cc73/doc/tutorial/kubernetes/000077500000000000000000000000001474664451600212575ustar00rootroot00000000000000cue-lang-cue-db9cc73/doc/tutorial/kubernetes/README.md000066400000000000000000000002121474664451600225310ustar00rootroot00000000000000# Kubernetes tutorial The Kubernetes tutorial has moved to https://github.com/cue-labs/cue-by-example/tree/main/003_kubernetes_tutorial. cue-lang-cue-db9cc73/encoding/000077500000000000000000000000001474664451600162665ustar00rootroot00000000000000cue-lang-cue-db9cc73/encoding/doc.go000066400000000000000000000032201474664451600173570ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package encoding contains subpackages to convert CUE to and from byte-level // and textual representations. // // For some packages, CUE can be mapped to both concrete values and higher-level // definitions. For instance, a Go value can be mapped based on its concrete // values or on its underlying type. Similarly, the protobuf package can extract // CUE definitions from .proto definitions files, but also convert proto // messages to concrete values. // // To clarify between these cases, we adopt the following naming convention: // // Name Direction Level Example // Decode x -> CUE Value Convert an incoming proto message to CUE // Encode CUE -> x Value Convert CUE to JSON // Extract x -> CUE Type Extract CUE definition from .proto file // Generate CUE -> x Type Generate OpenAPI definition from CUE // // To be more precise, Decoders and Encoders deal with concrete values only. // // Unmarshal and Marshal are used if the respective Decoder and Encoder decode // and encode from and to a stream of bytes. package encoding cue-lang-cue-db9cc73/encoding/gocode/000077500000000000000000000000001474664451600175265ustar00rootroot00000000000000cue-lang-cue-db9cc73/encoding/gocode/doc.go000066400000000000000000000016011474664451600206200ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:generate go run testdata/gen.go // Package gocode defines functions for extracting CUE definitions from Go code // and generating Go code from CUE values. // // This package is used for offline processing. For converting Go values to and // from CUE at runtime, use the gocodec package. package gocode cue-lang-cue-db9cc73/encoding/gocode/gen_test.go000066400000000000000000000075021474664451600216710ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build !gen package gocode import ( "bytes" "regexp" "strings" "testing" "cuelang.org/go/cue/errors" "cuelang.org/go/encoding/gocode/testdata/pkg1" "cuelang.org/go/encoding/gocode/testdata/pkg2" ) type validator interface { Validate() error } func TestPackages(t *testing.T) { testCases := []struct { name string value validator want string }{{ name: "failing int", value: pkg2.PickMe(4), want: "invalid value 4 (out of bound >5):\n pkg2/instance.cue:x:x", }, { name: "failing field with validator", value: &pkg1.OtherStruct{A: "car"}, want: ` 2 errors in empty disjunction: conflicting values null and {A:strings.ContainsAny("X"),P:"cuelang.org/go/encoding/gocode/testdata/pkg2".PickMe} (mismatched types null and struct): pkg1/instance.cue:x:x A: invalid value "car" (does not satisfy strings.ContainsAny("X")): pkg1/instance.cue:x:x _:1:4 pkg1/instance.cue:x:x `, }, { name: "failing field of type int", value: &pkg1.MyStruct{A: 11, B: "dog"}, want: ` 2 errors in empty disjunction: conflicting values null and {A:<=10,B:(=~"cat"|*"dog"),O?:OtherStruct,I:"cuelang.org/go/encoding/gocode/testdata/pkg2".ImportMe} (mismatched types null and struct): pkg1/instance.cue:x:x A: invalid value 11 (out of bound <=10): pkg1/instance.cue:x:x `, }, { name: "failing nested struct ", value: &pkg1.MyStruct{A: 5, B: "dog", O: &pkg1.OtherStruct{A: "car", P: 6}}, want: ` 4 errors in empty disjunction: conflicting values null and {A:<=10,B:(=~"cat"|*"dog"),O?:OtherStruct,I:"cuelang.org/go/encoding/gocode/testdata/pkg2".ImportMe} (mismatched types null and struct): pkg1/instance.cue:x:x O: 2 errors in empty disjunction: O: conflicting values null and {A:strings.ContainsAny("X"),P:"cuelang.org/go/encoding/gocode/testdata/pkg2".PickMe} (mismatched types null and struct): pkg1/instance.cue:x:x pkg1/instance.cue:x:x O.A: invalid value "car" (does not satisfy strings.ContainsAny("X")): pkg1/instance.cue:x:x _:1:4 pkg1/instance.cue:x:x `, }, { name: "fail nested struct of different package", value: &pkg1.MyStruct{A: 5, B: "dog", O: &pkg1.OtherStruct{A: "X", P: 4}}, want: ` 4 errors in empty disjunction: conflicting values null and {A:<=10,B:(=~"cat"|*"dog"),O?:OtherStruct,I:"cuelang.org/go/encoding/gocode/testdata/pkg2".ImportMe} (mismatched types null and struct): pkg1/instance.cue:x:x O: 2 errors in empty disjunction: O: conflicting values null and {A:strings.ContainsAny("X"),P:"cuelang.org/go/encoding/gocode/testdata/pkg2".PickMe} (mismatched types null and struct): pkg1/instance.cue:x:x pkg1/instance.cue:x:x O.P: invalid value 4 (out of bound >5): pkg2/instance.cue:x:x `, }, { name: "all good", value: &pkg1.MyStruct{ A: 5, B: "dog", I: &pkg2.ImportMe{A: 1000, B: "a"}, }, want: "nil", }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got := strings.TrimSpace(errStr(tc.value.Validate())) want := strings.TrimSpace(tc.want) if got != want { t.Errorf("got:\n%q\nwant:\n%q", got, want) } }) } } func errStr(err error) string { if err == nil { return "nil" } buf := &bytes.Buffer{} errors.Print(buf, err, nil) r := regexp.MustCompile(`.cue:\d+:\d+`) return r.ReplaceAllString(buf.String(), ".cue:x:x") } cue-lang-cue-db9cc73/encoding/gocode/generator.go000066400000000000000000000172461474664451600220550ustar00rootroot00000000000000// Copyright 2019 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gocode import ( "bytes" "cmp" "fmt" "go/ast" "go/format" "go/types" "text/template" "golang.org/x/tools/go/packages" "cuelang.org/go/cue" "cuelang.org/go/cue/errors" ) // Config defines options for generation Go code. type Config struct { // Prefix is used as a prefix to all generated variables. It defaults to // cuegen. Prefix string // ValidateName defines the default name for validation methods or prefix // for validation functions. The default is "Validate". Set to "-" to // disable generating validators. ValidateName string // CompleteName defines the default name for complete methods or prefix // for complete functions. The default is "-" (disabled). CompleteName string // The cue.Runtime variable name to use for initializing Codecs. // A new Runtime is created by default. RuntimeVar string } const defaultPrefix = "cuegen" // Generate generates Go code for the given instance in the directory of the // given package. // // Generate converts top-level declarations to corresponding Go code. By default, // it will only generate validation functions of methods for exported top-level // declarations. The behavior can be altered with the @go attribute. // // The go attribute has the following form @go({,